【问题标题】:TCP File Send issue in .NET, NetworkStream Socket.NET 中的 TCP 文件发送问题,NetworkStream 套接字
【发布时间】:2014-06-11 17:39:30
【问题描述】:

我正在使用以下代码通过 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];
        }    
    }
}

【问题讨论】:

  • 根据答案,发送部分是错误的。也许接收部分也坏了。贴出代码。
  • 请注意,依赖 HTTP 等标准协议更容易。套接字很难使用。
  • 实际上发送和接收部分都在工作,我不是在寻找完成这些工作的方法。我不能使用 Http 我在很多方面都受到环境、要求和策略的限制(WinCE)

标签: c# tcp networkstream


【解决方案1】:

BeginSend 是一个异步操作。它只保证在你调用它之后启动,它不会立即完成。只要套接字正在发送传递的数据,就不能改变该数据。 操作结束将通过AsyncCallback 回调参数发出信号。

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

解决问题的其他方法:

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

【讨论】:

  • 我没有看到任何关于你所说的缓冲区的文档。我认为 BeginSend 可能会在本地从我的缓冲区复制数据,然后将我的请求排入队列。你有什么参考吗?
  • 我可以在调用第一个回调和调用第一个 EndSend 并且正确接收所有内容之前将所有内容排队。这似乎证明了我所说的
  • 此外,我在第二次调用我的方法时面临第一个块的问题(仅当我不更新缓冲区时)。由于缓冲区是方法本地的,所以我也不应该遇到这个问题:当我调用方法时,它是一个新的缓冲区。
  • 刚刚尝试查找。似乎没有明确写在文档中。但也没有写入缓冲区被复制。事实上,Send 方法的重点是将给定缓冲区的副本复制到套接字的底层 OS 缓冲区中。如果 .NET 会制作一个额外的副本,那么效率会很低(所有内容都必须复制两次),并且会损害规避流控制,并且根本不需要异步方法。
  • 底层 Win32 API 的文档明确提到:msdn.microsoft.com/de-de/library/windows/desktop/…For a Winsock application, once the WSASend function is called, the system owns these buffers and the application may not access them. This array must remain valid for the duration of the send operation.
猜你喜欢
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 2015-01-30
  • 2015-02-07
  • 2020-04-28
  • 2017-03-14
  • 2011-06-17
  • 1970-01-01
相关资源
最近更新 更多