c# - 表明已通过网络接收到所有数据的最佳方式?

标签 c# networking tcp tcpclient tcplistener

我有一个运行良好的客户端/服务器应用程序,但它缺少使它更可靠的一个关键行为。

目前,它在网络能力上还远谈不上“强”。我正在努力做到这一点,研究让我相信我需要某种适当的协议(protocol)来确保在网络传输期间没有数据丢失。

我听说过几种方法。我认为最适合我们情况的方法是使用终止符,例如 <EOF>。标签。我的问题是我不确定实现它的最佳方法。

这里有几个代码片段,我将在找出最佳解决方案后对其进行修改以包含终止符。

客户:

TcpClient client = new TcpClient();

client.Connect(hostname, portNo);

using (var stream = client.GetStream())
{
    //send request

    stream.Write(data, 0, data.Length);
    stream.Flush();

    //read server response

    if (stream.CanRead)
    {
        byte[] buffer = new byte[1024];
        string response = "";
        int bytesRead = 0;

        do
        {
            bytesRead = stream.Read(buffer, 0, buffer.Length);

            response += Encoding.ASCII.GetString(buffer, 0, bytesRead);

        } //trying to replace 'DataAvailable', it doesn't work well
        while (stream.DataAvailable); 
    }
}

请注意,我正在尝试替换 stream.DataAvailable检查流中更多数据的方法。它一直在引起问题。

服务器:

var listener = new TcpListener(IPAddress.Any, portNo);

listener.Start();

var client = listener.AcceptTcpClient();

using (var stream = client.GetStream())
{
    var ms = new System.IO.MemoryStream();

    byte[] buffer = new byte[4096];
    int bytesRead = 0;

    do
    {
        bytesRead = stream.Read(buffer, 0, buffer.Length);

        ms.Write(buffer, 0, bytesRead);

    } //also trying to replace this 'stream.DataAvailable'
    while (stream.DataAvailable);

    ms.Position = 0;

    string requestString = Encoding.UTF8.GetString(ms.ToArray());

    ms.Position = 0;

    /*
        process request and create 'response'
    */

    byte[] responseBytes = Encoding.UTF8.GetBytes(response);

    stream.Write(responseBytes, 0, responseBytes.Length);
    stream.Flush();
}

那么,鉴于这两个代码示例,我如何修改它们以同时包含和检查某种数据终止符以指示停止读取数据是安全的?

最佳答案

您可以依靠 TCP 在 FIN 之前传输所有数据。您的代码的问题是 available() 不是流结束的有效测试。这是对现在可用数据的测试。

所以你过早地终止了你的阅读循环,因此在接收方丢失了数据,并在发送方重置。

您应该只阻塞 Read() 方法,直到您从 API 收到 EOS 指示,无论是在 C# 中。

您不需要自己的额外 EOS 指标。

关于c# - 表明已通过网络接收到所有数据的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19640313/

相关文章:

java - 第一次网络连接到 s3 非常耗时

qt - 使用 QTcpSocket 的 Tcp 数据包

networking - 使用 bufio 从端口读取时出现 EOF 错误

c# - Publish().RefCount() 不工作?

c# - 如何在 Http GET 请求中容纳超过 29 个参数

c# - 如何在c#中检查并删除mysql插入查询失败然后删除插入的数据

silverlight - Silverlight 中的后端通信

c# - 带有自定义错误信号的条件行为

qt - QSocketNotifier : socket notifiers cannot be disabled from another thread

Java 客户端和 Erlang 服务器?