通过 TCPClient c# 发送大图像

Sending large image through TCPClient c#

我有以下代码可以将图片发送到接收应用程序

public static void sendFile(string file, string ip)
    {

        using (TcpClient client = new TcpClient())
        {
            client.Connect(IPAddress.Parse(ip), 44451);
            //Console.WriteLine(ip);
            NetworkStream nwStream = client.GetStream();

            MemoryStream ms = new MemoryStream();
            Image x = Image.FromFile(file);
            x.Save(ms, x.RawFormat);

            byte[] bytesToSend = ms.ToArray();

            nwStream.Write(bytesToSend, 0, bytesToSend.Length);
            nwStream.Flush();
            client.Close();
        }
    }

我在另一端收到文件

            NetworkStream nwStream = clientCopy.GetStream();
        byte[] buffer = new byte[clientCopy.ReceiveBufferSize];


        //---read incoming stream---
        int bytesRead = nwStream.Read(buffer, 0, clientCopy.ReceiveBufferSize);


MemoryStream ms = new MemoryStream(buffer);
            Image returnImage = Image.FromStream(ms);
            //ms.Flush();
            //ms.Close();
            String path;

            if (!Directory.Exists(path = @"C:\Users\acer\AppData\Roaming\test"))
            {
                Directory.CreateDirectory(@"C:\Users\acer\AppData\Roaming\test");
            }

            string format;
            if (ImageFormat.Jpeg.Equals(returnImage.RawFormat))
            {
                format = ".jpg";
            }
            else if (ImageFormat.Png.Equals(returnImage.RawFormat))
            {
                format = ".png";
            }
            else
            {
                format = ".jpg";
            }

            returnImage.Save(@"C:\Users\acer\AppData\Roaming\test\default_pic" + format, returnImage.RawFormat);

如果我发送的图片很小(大约 <20kb),另一端会 100% 收到文件,但如果我发送的文件大约 >=100kb,则会收到图片,但只有一半图像已加载。我知道在读取所有数据之前读取流的方法,但我不知道如何正确实现它。

谢谢

您只调用了一次 Read,当然不能保证读取所有字节。您可以循环,调用 Read 并在每次迭代时复制相关字节数,或者您可以使用 Stream.CopyTo:

var imageStream = new MemoryStream();
nwStream.CopyTo(imageStream);
// Rewind so that anything reading the data will read from the start
imageStream.Position = 0;

...或者您可以直接从网络流中读取图像:

// No need for another stream...
Image returnImage = Image.FromStream(nwStream);

可能 由于流不可搜索而失败...在这种情况下,如上使用 CopyTo 将是最简单的选择。)

TCP 协议(​​与任何其他流协议一样)不能用于按原样传输数据。大多数时候,不可能知道是否所有数据都已到达,或者是否收到了与预期数据不相关的数据块。因此,几乎总是需要定义底层协议,例如通过发送消息 header(如在 HTTP 中)或定义消息分隔符(如 Telnet 中的换行符;但是,对大消息使用分隔符是不切实际的) .在最简单的情况下,定义非常简单的 header 就足够了,它只包含消息的长度

因此,在您的情况下,您可以发送 4 字节的图像长度,然后再发送图像。在服务器端,您将读取 4 字节大小,然后在循环中调用 Read 直到收到完整的消息。

请注意,您可能会收到比预期更多的字节。这意味着最后一个块包含下一条消息的开头。