.NET,NetworkStream Socket中的TCP文件发送问题

时间:2014-06-11 09:09:03

标签: c# tcp networkstream

我正在使用以下代码通过tcp发送文件。

如果我连续多次发送同一个文件以测试它是否健壮,我会正确收到第一个文件而另一个文件搞砸了。

所有混乱的文件具有相同的错误字节,如果我睡眠(一会儿)所有文件都正确传输。我注意到我必须在读取我的文件时实例化一个新缓冲区才能完成所有工作。但我不明白为什么。

我担心我重新修复缓冲区的解决方案可能只是隐藏了另一个主要问题。有什么建议吗?

using(var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
    using(var binaryReader = new BinaryReader(fileStream))
    {
        var _sendingBuffer = new byte[BUFFER_SIZE];

        int length = (int)fileStream.Length;
        int bytesRead = 0;

        //Ensure we reached the end of the stream regardless of encoding
        while (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
        {
            bytesRead = binaryReader.Read( _sendingBuffer, 0, _sendingBuffer.Length);

            _socket.BeginSend(_sendingBuffer, 0, bytesRead, SocketFlags.None, SendFileCallback, null);

            //without this i received some messed up data
            _sendingBuffer = new byte[BUFFER_SIZE];
        }    
    }
}

1 个答案:

答案 0 :(得分:2)

BeginSend是一个异步操作。它只会保证在你打电话后开始,它不会马上完成。只要套接字正在发送传递的数据,就不能改变该数据。 操作结束将通过AsyncCallback回调参数发出信号。

您的问题正是您在传输仍在进行时突变了传输缓冲区。为每个传输调用创建一个新数组可以解决这个问题。

解决问题的其他方法:

  • 使用阻塞Socket.Send函数,该函数将阻塞,直到发送整个数据并且可以重用缓冲区。这也会使您的错误处理变得更加容易,因为错误不会显示在AsyncCallback
  • 让您的完整程序异步执行,例如使用C#5的异步任务和异步/等待功能 因此:
    1. 首先异步读取文件的一部分。
    2. 异步读取完成后,通过套接字
    3. 异步发送
    4. 当此操作完成并且有更多数据需要阅读时,请返回1.