C#通过互联网发送文件

时间:2011-11-25 14:49:30

标签: c# file tcp send

我设法使用NetworkStream和套接字通过TCP发送二进制数据。 我唯一的问题是,当我发送较大的文件,如几百KB图像时,它们无法正确传输,图像的一半丢失。在服务器端我Socket.Send传输数据。在客户端,我使用Socket.BeginReceive一个1024大小的缓冲区写入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方法,数据仍然有时会损坏。

3 个答案:

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

答案 1 :(得分:0)

最有可能(猜测)你没有正确地从客户端的流中读取。

您需要读取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!
}

答案 2 :(得分:0)

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