2011-11-25 148 views
0

我设法通过TCP使用NetworkStream和套接字发送二进制数据。 我唯一的问题是,当我发送较大的文件,如几百KB的图像,他们没有得到正确的传输,图像的一半丢失。在服务器端I Socket.Send传输数据。在客户端,我使用Socket.BeginReceive1024大小的缓冲区,将其写入MemoryStream,稍后使用new Bitmap(Stream)将该MemoryStream转换为可在PictureBox中显示的图像。C#通过互联网发送文件

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

编辑:代码发布

  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(); 

编辑:数据仍然是腐败有时甚至与睡眠方法。

+3

请发布您的代码,以便发现错误。 – Oded

+3

发布您的代码。如果没有,我们只是猜测。 – ChrisF

+0

这看起来没问题,所以假设它不是网络问题,在发送方或接收方都有问题,我们需要查看该代码。 – nos

回答

0

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

0

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

你需要阅读EndReceive()方法的结果,看看你实际上有多少数据读取 - 这可能不是你的缓冲区的大小(1024个字节在这种情况下)

所以:
一)当调用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! 
} 
+0

好点,但我意识到这一点,即使仍然有数据等待传输,它似乎是NetworkStream.DataAvailable报告错误的问题。 – thencz

+2

@Tibor Hencz您误解了DataAvailable属性。它不会告诉你发送端可能有一些未来的数据可以发送给你,它会告诉你是否有可用的数据,在你的接收端点* NOW *处。如果你读的速度比另一方快,那么在这个特定的时间,没有数据到达你的主机,但是在3纳秒时,一些数据会到达?你应该继续阅读,直到发送端关闭流(或者直到发生大的超时) – nos

+0

是的,这正是我的代码应该做的,检查是否有数据到达设备并读取它,如果有的话。我在这个示例代码中看到它:http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable.aspx – thencz

1

我建议你改变这种循环:

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阻塞,直到有一些数据或套接字关闭(或抛出一些异常)。我删除了无用的睡眠。