【问题标题】:C# sending files over internetC# 通过互联网发送文件
【发布时间】:2012-01-06 10:19:21
【问题描述】:

我设法使用NetworkStream 和套接字通过TCP 发送二进制数据。 我唯一的问题是,当我发送像几百 KB 图像这样的较大文件时,它们无法正确传输,图像的一半丢失了。在服务器端我Socket.Send 来传输数据。在客户端,我使用Socket.BeginReceive1024 大小的缓冲区,该缓冲区被写入MemoryStream,稍后我使用new Bitmap(Stream)MemoryStream 转换为可以在PictureBox 中显示的图像。

我应该使用什么方法来避免数据丢失?

编辑:发布代码

            listener = new TcpListener(myAddress, 86);
            listener.Start();
            TcpClient client = listener.AcceptTcpClient();
            ns = client.GetStream();
            byte[] buffer = new byte[1024];
            while (fileTransfer)
            {
                ms = new MemoryStream();
                do
                {
                    int length = ns.Read(buffer, 0, buffer.Length);
                    ms.Write(buffer, 0, length);
                    // with this line added the data loss apparently disappears
                    System.Threading.Thread.Sleep(1);
                } while (ns.DataAvailable);
                UpdateData();
                ms.Dispose();
                System.Threading.Thread.Sleep(10);
            }
            ns.Dispose();
            client.Close();
            listener.Stop();

编辑:即使使用 sleep 方法,数据有时仍会损坏。

【问题讨论】:

  • 请张贴您的代码,以便您发现错误。
  • 发布您的代码。没有它,我们只是在猜测。
  • 这似乎没问题,所以假设这不是网络问题,您在发送端或接收端的某个地方有错误,我们需要查看该代码。

标签: c# file tcp send


【解决方案1】:

很可能(猜测)您没有正确地从客户端的流中读取数据。

您需要读取 EndReceive ( ) 方法的结果以查看您实际读取了多少数据 - 它可能不是缓冲区的大小(在这种情况下为 1024 字节)

所以:
a) 在调用 BeginReceive 时,您是否传递了回调?
b)如果是,您是否正在读取此结果并将适当数量的字节写入您的内存流?

即:

public void ReceiveCallback( IAsyncResult result)
{

    var buffer = (byte[])result.AsyncState;
    int bytesRead = socket.EndReceive();
    memoryStream.Write (buffer, 0, bytesRead);//bytesRead may not be 1024!
}

【讨论】:

  • 好点,但我知道这一点,NetworkStream.DataAvailable 报告错误似乎是一个问题,即使仍有数据等待传输。
  • @Tibor Hencz 您误解了 DataAvailable 属性。它不会告诉您发送方可能有一些未来数据要发送给您,它会告诉您是否有可用的数据,在您的接收端点NOW。如果你读的比对方写的快,而且在这个特定的时间,没有数据到达你的主机,但是在 3 纳秒内一些数据会到达怎么办?您应该继续阅读,直到发送方关闭流(或直到发生大超时)
  • 是的,这正是我的代码应该做的,检查设备上是否有数据到达,如果有就读取它。我在这个示例代码中看到了它:msdn.microsoft.com/en-us/library/…
【解决方案2】:

我建议你改变这个循环:

do
{
    int length = ns.Read(buffer, 0, buffer.Length);
    ms.Write(buffer, 0, length);
    // with this line added the data loss apparently disappears
    System.Threading.Thread.Sleep(1);
} while (ns.DataAvailable);

进入:

do
{
    int length = ns.Read(buffer, 0, buffer.Length);
    ms.Write(buffer, 0, length);
} while (length > 0);

即读取到数据结束(即ns.Read 不返回数据)。 Read 阻塞,直到有一些数据或套接字关闭(或抛出一些异常)。我去掉了无用的睡眠。

【讨论】:

    【解决方案3】:

    好的,我通过在发送实际数据之前发送数据的大小来解决它。它不起作用的原因是我错误地认为转移是立即的。这就是接收器循环中的 Sleep() 方法有所不同但没有解决问题的原因。我知道在这种情况下我不能依赖 DataAvailable。即使检查接收数据的长度也不起作用,因为客户端可能会在循环完成后发送数据。检查文件大小(如果数据大于接收端的缓冲区)是我找到这么久的最佳解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      相关资源
      最近更新 更多