Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 发送少量数据几分钟后,windows计算机上的TCP发送方计算机接收方窗口大小缩小为0_C#_.net_Networking_Tcp_Tcpclient - Fatal编程技术网

C# 发送少量数据几分钟后,windows计算机上的TCP发送方计算机接收方窗口大小缩小为0

C# 发送少量数据几分钟后,windows计算机上的TCP发送方计算机接收方窗口大小缩小为0,c#,.net,networking,tcp,tcpclient,C#,.net,Networking,Tcp,Tcpclient,我正在编写一个在windows笔记本电脑上运行的应用程序,它在一个循环中发送TCP字节作为“自制保持活动”消息,以保持连接处于活动状态(服务器机器在15秒未收到TCP数据后将断开连接)。只要连接处于活动状态,“服务器机器”就会向笔记本电脑发送小块数据(大约.5K字节/秒)(根据服务器文档,这是理想情况,这是一个“echo”数据包,但我无法找到如何在.NET中实现这一点)。我的问题是,当我在Wireshark中查看这些数据时,我可以看到良好的网络活动,然后,几分钟后,“win”(笔记本电脑上可用的

我正在编写一个在windows笔记本电脑上运行的应用程序,它在一个循环中发送TCP字节作为“自制保持活动”消息,以保持连接处于活动状态(服务器机器在15秒未收到TCP数据后将断开连接)。只要连接处于活动状态,“服务器机器”就会向笔记本电脑发送小块数据(大约.5K字节/秒)(根据服务器文档,这是理想情况,这是一个“echo”数据包,但我无法找到如何在.NET中实现这一点)。我的问题是,当我在Wireshark中查看这些数据时,我可以看到良好的网络活动,然后,几分钟后,“win”(笔记本电脑上可用的接收窗口大小)从65K缩减到0,增量约为每个数据包240字节。为什么会发生这种情况?我该如何预防?我似乎无法让.Net中的“keep alive”标志正常工作,所以这应该是我的解决方法。我没有看到任何丢失的ACK消息,而且我的数据速率约为2Kb/秒,因此我不明白笔记本电脑窗口大小为什么会下降。我肯定认为我对TCP和/或windows/.NET使用TCPsockets存在误解,因为我没有使用TCP的经验(我一直使用UDP)


您应该非常熟悉TCP的定义。它解释了wondow以及如何将其用于流量控制:

流量控制:

TCP为接收方提供了一种控制数据量的方法 由发件人发送。这是通过使用返回“窗口”来实现的 每一个ACK都指示超出该范围的可接受序列号的范围 最后一段成功接收。该窗口指示允许的操作 发送方在进一步接收之前可以发送的八位字节数 允许

-及-

为了控制TCP之间的数据流,需要一种流控制机制 雇佣。接收TCP向发送TCP报告一个“窗口”。 此窗口指定八位字节数,从 接收TCP当前准备发送的确认号 接受

-及-

窗口:16位

数据八位字节的数量,以 此段的发件人愿意接收的确认字段 接受

窗口大小由数据接收器在其确认接收数据的ACK段中指定。如果您的笔记本电脑接收窗口缩小到
0
,则它会将窗口设置为该窗口,因为它没有更多的接收空间,需要时间来处理并释放接收缓冲区中的空间。当它有更多的空间时,它将发送一个带有较大窗口的ACK段

段接收测试
长度窗口
------- -------  -------------------------------------------
0 0 SEG.SEQ=RCV.NXT
0>0 RCV.NXT=0不可接受
>0>0 RCV.NXT=
请注意,当接收窗口为零时,不应显示任何段 除ACK段外,可接受。因此,TCP有可能 在传输数据和接收数据时保持零接收窗口 阿克斯。但是,即使接收窗口为零,TCP也必须 处理所有传入段的RST和URG字段


你真的在读另一边的数据吗?如果另一方无法正确接收数据,TCP将停止发送数据。当然,您还应该读取服务器在客户端发送给您的数据。记住,TCP不像UDP那样是发送和忘记。您不能忽略即将到来的数据。@Luaan感谢您的回复。我没有访问服务器机器的权限,但当我执行“伪保持活动”数据包时,我确实看到来自该机器的握手。在我连接之后,服务器机器确实会向我发送数据,并且窗口大小看起来没有什么异常(服务器机器保持几乎恒定的窗口大小)。我的笔记本电脑窗口在收到随机数量的数据包后会缩小。我唯一的检查方法就是在笔记本电脑上安装Wireshark。我打算在“保持活动”工作后读取数据流,但我不想让问题变得更加复杂。窗口大小由另一端设置。当另一端已满并且需要处理接收到的数据时,它将收缩到“0”。当另一端处理了足够的数据以再次接收更多数据时,它将重新增长。等等,你所说的“伪保持活动”数据包到底是什么意思?服务器是否理解您发送的内容?您不能只发送随机数据,期望事情正常运行—不要忘记,与UDP不同,TCP与独立消息无关—它与数据流有关。如果您发送的是无意义的数据(或者更糟的是,部分消息),整个连接将变得相当不可预测。我更新了我的问题,因为我不清楚是笔记本电脑接收窗口实际在缩小,对于这种混乱,我很抱歉。笔记本电脑窗口大小减小为0(笔记本电脑发出的ACK消息显示此信息)。所以我的笔记本电脑正在发送虚拟数据。“服务器接收”窗口从不下降太多。我的困惑是“为什么”笔记本电脑的TCP接收窗口减少到0?我的代码错了吗?服务器文档指出,我应该使用“echo”数据包,而不是发送无意义的数据来保持连接,但是.net在此上没有文档确定,服务器正在向您的笔记本电脑发送数据。您是否正在处理笔记本电脑中的数据,以便清空接收缓冲区?听起来数据只是在填充缓冲区,而窗口也在缩小:“win”(笔记本电脑上提供的接收窗口大小)从65K缩小到0,每个数据包的增量约为240字节。”听起来服务器每段发送的数据约为240字节,这就是你的缓冲区填充。我猜你在这方面是100%正确的,但我会找一些关于清空缓冲区的文档
                    TcpClient client = new TcpClient(iPEndpoint);
                    //Socket s = client.Client; none of these flags actually work on the keep alive feature
                    //s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                    //s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 10);
                    //s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 10);
    
                    // Translate the passed message into ASCII and store it as a Byte array.
                    // Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
    
                    IPAddress ipAdd = IPAddress.Parse("192.168.1.10"); 
                    IPEndPoint ipEndPoin = new IPEndPoint(ipAdd, 13000);
                    client.Connect(ipEndPoin);
    
                    NetworkStream stream = client.GetStream();
    
                    // Send the message to the connected TcpServer.
                    bool finished = false;
                    while (!finished)
                    {
                        try
                        {
                            stream.Write(data, 0, data.Length);
                            Thread.Sleep(5000);
                        }
                        catch (System.IO.IOException ioe)
                        {
                            if (ioe.InnerException is System.Net.Sockets.SocketException)
                            {
                                client.Dispose();
                                client = new TcpClient(iPEndpoint);
                                client.Connect(ipEndPoin); 
                                stream = client.GetStream(); 
                                Console.Write("reconnected");
                                // this imediately fails again after exiting this catch to go back to the while loop because send window is still 0
                            }
                        }
                    }
Segment Receive  Test
Length  Window
------- -------  -------------------------------------------

   0       0     SEG.SEQ = RCV.NXT

   0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

  >0       0     not acceptable

  >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
              or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND