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" - 永远不要将数据复制到新的单独字节数组中。