TCPClient.Read 读取低至 4 字节的块
TCPClient.Read Reading in chunks of as low as 4 bytes
我完全理解如果数据尚未到达,我将无法读取分配的最大值。但是以4字节的速度读取真的合理吗?我的意思是,如果我收到一张 100000 字节的图像,那将花费很长时间。
我在接收或发送图片时是否存在明显问题?
**** 澄清一下:下面的 rLength 每次都会变化,有时我只会收到 4 个字节,而在那个 while 循环中只有 4 个字节,其他时候我会收到 3000,而在循环中只有 3000。我很确定有更多数据,但它似乎停留在每次循环只读取 x 数量****
这里是服务器端的接收代码
int totalBuffer, totalRecieved = 0;
byte[] totalBufferByte = new byte[4];
byte[] buffer = new byte[0];
byte[] tbuffer;
int rLength, prevLength;
stream.Read(totalBufferByte, 0, totalBufferByte.Length);
totalBuffer = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buf = new byte[8192];
while (totalBuffer > totalRecieved)
{
rLength = stream.Read(buf, 0, buf.Length);
totalRecieved = rLength + totalRecieved;
Console.WriteLine("totalRecieved len: " + totalRecieved + " " + totalBuffer + " " + rLength + " " + buf.Length);
if (rLength < buf.Length)
{
byte[] temp = new byte[rLength];
Array.Copy(buf, temp, rLength);
buf = temp;
}
prevLength = buffer.Length;
tbuffer = buffer;
buffer = new byte[buffer.Length + rLength];
Array.Copy(tbuffer, buffer, tbuffer.Length);
buf.CopyTo(buffer, prevLength);
}
这里是发送码
public void SendResponse(int command, Object[] args)
{
if (ClientSocket == null)
{
Console.WriteLine("Command: ClientSocket");
return;
}
var serverStream = this.ClientSocket.GetStream();
if (!serverStream.CanRead || !serverStream.CanWrite)
{
Console.WriteLine("Command: serverStream Error");
return;
}
byte[] toSend = null;
switch (command)
{
// 0 - genneral, 1 - handshake response
case 0:
toSend = Encoding.ASCII.GetBytes(args[0].ToString());
break;
case 1:
Rectangle bounds = Screen.GetBounds(Point.Empty);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
toSend = ImageToByte(bitmap);
}
break;
}
try
{
byte[] bufferedToSend = new byte[toSend.Length + 4];
byte[] lengthOfSend = BitConverter.GetBytes(toSend.Length);
Array.Copy(lengthOfSend, bufferedToSend, 4);
toSend.CopyTo(bufferedToSend, 4);
serverStream.Write(bufferedToSend, 0, bufferedToSend.Length);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
这至少是问题的一部分:
rLength = stream.Read(buf, 0, buf.Length);
...
if (rLength < buf.Length)
{
byte[] temp = new byte[rLength];
Array.Copy(buf, temp, rLength);
buf = temp;
}
基本上,您将下一次阅读限制为 最多 上一次阅读的大小。
不清楚你真正想做什么,但听起来你应该有类似的东西:
byte[] lengthBuffer = new byte[4];
int lengthRead = stream.Read(lengthBuffer, 0, lengthBuffer.Length);
// TODO: Throw or loop if you haven't read 4 bytes...
int length = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buffer = new byte[length];
int lengthRead = 0;
while (lengthRead < length)
{
int chunkRead = stream.Read(buffer, lengthRead,
length - lengthRead);
if (chunkRead == 0)
{
throw new IOException(
"Stream ended after reading {0} out of {1} bytes",
lengthRead, length);
}
lengthRead += chunkRead;
}
换句话说,您应该始终要求阅读 "however much data is left" - 永远不要将数据复制到新的单独字节数组中。
我完全理解如果数据尚未到达,我将无法读取分配的最大值。但是以4字节的速度读取真的合理吗?我的意思是,如果我收到一张 100000 字节的图像,那将花费很长时间。
我在接收或发送图片时是否存在明显问题?
**** 澄清一下:下面的 rLength 每次都会变化,有时我只会收到 4 个字节,而在那个 while 循环中只有 4 个字节,其他时候我会收到 3000,而在循环中只有 3000。我很确定有更多数据,但它似乎停留在每次循环只读取 x 数量****
这里是服务器端的接收代码
int totalBuffer, totalRecieved = 0;
byte[] totalBufferByte = new byte[4];
byte[] buffer = new byte[0];
byte[] tbuffer;
int rLength, prevLength;
stream.Read(totalBufferByte, 0, totalBufferByte.Length);
totalBuffer = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buf = new byte[8192];
while (totalBuffer > totalRecieved)
{
rLength = stream.Read(buf, 0, buf.Length);
totalRecieved = rLength + totalRecieved;
Console.WriteLine("totalRecieved len: " + totalRecieved + " " + totalBuffer + " " + rLength + " " + buf.Length);
if (rLength < buf.Length)
{
byte[] temp = new byte[rLength];
Array.Copy(buf, temp, rLength);
buf = temp;
}
prevLength = buffer.Length;
tbuffer = buffer;
buffer = new byte[buffer.Length + rLength];
Array.Copy(tbuffer, buffer, tbuffer.Length);
buf.CopyTo(buffer, prevLength);
}
这里是发送码
public void SendResponse(int command, Object[] args)
{
if (ClientSocket == null)
{
Console.WriteLine("Command: ClientSocket");
return;
}
var serverStream = this.ClientSocket.GetStream();
if (!serverStream.CanRead || !serverStream.CanWrite)
{
Console.WriteLine("Command: serverStream Error");
return;
}
byte[] toSend = null;
switch (command)
{
// 0 - genneral, 1 - handshake response
case 0:
toSend = Encoding.ASCII.GetBytes(args[0].ToString());
break;
case 1:
Rectangle bounds = Screen.GetBounds(Point.Empty);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
toSend = ImageToByte(bitmap);
}
break;
}
try
{
byte[] bufferedToSend = new byte[toSend.Length + 4];
byte[] lengthOfSend = BitConverter.GetBytes(toSend.Length);
Array.Copy(lengthOfSend, bufferedToSend, 4);
toSend.CopyTo(bufferedToSend, 4);
serverStream.Write(bufferedToSend, 0, bufferedToSend.Length);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
这至少是问题的一部分:
rLength = stream.Read(buf, 0, buf.Length);
...
if (rLength < buf.Length)
{
byte[] temp = new byte[rLength];
Array.Copy(buf, temp, rLength);
buf = temp;
}
基本上,您将下一次阅读限制为 最多 上一次阅读的大小。
不清楚你真正想做什么,但听起来你应该有类似的东西:
byte[] lengthBuffer = new byte[4];
int lengthRead = stream.Read(lengthBuffer, 0, lengthBuffer.Length);
// TODO: Throw or loop if you haven't read 4 bytes...
int length = BitConverter.ToInt32(totalBufferByte, 0);
byte[] buffer = new byte[length];
int lengthRead = 0;
while (lengthRead < length)
{
int chunkRead = stream.Read(buffer, lengthRead,
length - lengthRead);
if (chunkRead == 0)
{
throw new IOException(
"Stream ended after reading {0} out of {1} bytes",
lengthRead, length);
}
lengthRead += chunkRead;
}
换句话说,您应该始终要求阅读 "however much data is left" - 永远不要将数据复制到新的单独字节数组中。