C# “随机”;远程主机强制关闭了现有连接。”;在TCP重置之后
我有两个部分,一个客户端和一个服务器。我尝试将数据(大小>5840字节)从客户端发送到服务器,然后服务器将数据发送回服务器。我循环了很多次,每次循环之间等待一秒钟。有时服务器应用程序崩溃,崩溃似乎非常随机,错误如下: 未处理的异常:System.IO.IOException:无法从传输连接读取数据:远程主机强制关闭了现有连接。--> System.Net.Sockets.SocketException:远程主机强制关闭了现有连接 位于System.Net.Sockets.Socket.Receive(字节[]缓冲区、Int32偏移量、Int32大小、SocketFlags和SocketFlags) 位于System.Net.Sockets.NetworkStream.Read(字节[]缓冲区,Int32偏移量,Int32 s (放大) ---内部异常堆栈跟踪的结束--- 位于System.Net.Sockets.NetworkStream.Read(字节[]缓冲区,Int32偏移量,Int32 s (放大) 在TCP_Server.Program.Main上(字符串[]args) 客户端代码(在循环中): 服务器代码:C# “随机”;远程主机强制关闭了现有连接。”;在TCP重置之后,c#,.net,sockets,tcp,wireshark,C#,.net,Sockets,Tcp,Wireshark,我有两个部分,一个客户端和一个服务器。我尝试将数据(大小>5840字节)从客户端发送到服务器,然后服务器将数据发送回服务器。我循环了很多次,每次循环之间等待一秒钟。有时服务器应用程序崩溃,崩溃似乎非常随机,错误如下: 未处理的异常:System.IO.IOException:无法从传输连接读取数据:远程主机强制关闭了现有连接。--> System.Net.Sockets.SocketException:远程主机强制关闭了现有连接 位于System.Net.Sockets.Socket.Recei
Byte[] bytes = new Byte[size];
// Enter the listening loop.
for (int i = 0; i < numberOfPackages; i++)
{
using (TcpClient client = server.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
{
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
// Loop to receive all the data sent by the client.
while ((stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Send back a response.
stream.Write(bytes, 0, size);
}
client.GetStream().Close();
client.Close();
}
Console.WriteLine("Receive data size " + size);
}
Byte[]bytes=新字节[大小];
//进入监听循环。
对于(int i=0;i
我使用wireshark监视发送的tcp包,发现在程序崩溃之前,tcp RST从客户端发送到服务器。所以我假设问题在于RST没有正确处理。
客户端和主机之间没有防火墙,所以这不是问题所在
客户端和服务器的wireshark文件如下:
所以,要么我需要摆脱TCP RST,要么我需要我的服务器以某种方式处理它而不崩溃
我已经尝试使用更长的等待时间,但没有帮助。
如果数据低于5840字节,我没有得到任何崩溃,我所知道的
有什么建议或想法吗
编辑:
多亏了这些答案,我才得以进行以下更改:
服务器:
// Loop to receive all the data sent by the client.
int k = 0;
while (k < size)
{
int bytesRead = stream.Read(bytes, 0, bytes.Length);
k += bytesRead;
}
// Send back a response.
stream.Write(bytes, 0, size);
//循环以接收客户端发送的所有数据。
int k=0;
while(k
在客户端接收时也是如此。因为我首先要发送所有数据,然后让服务器响应,这对我的应用程序很有效。我不是专家,但您不认为在客户端调用stream.Close()会在服务器仍在尝试写入时关闭流吗
// Send back a response.
stream.Write(bytes, 0, size);
另外,您可能需要放置一些数据以标记其结束,以便服务器知道并停止读取。我看到两个问题:
大小
字节的读取实际上将读取大小
字节。事实并非如此。TCP是一种流协议。读操作至少读取一个字节。这是唯一的保证修复这两个问题并报告您的发现。我通过增加iis根条目的缓存限制解决了相同的问题。您还可以禁用缓存。希望有帮助。我们在使用HttpClient随机错误时遇到了这个问题,例如
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
或
TCP堆栈中的显式拥塞通知(ECN)存在问题。这也称为ECN能力。显式拥塞通知是Internet协议和传输控制协议的扩展,在RFC 3168中定义。ECN允许在不丢弃数据包的情况下发送网络拥塞的端到端通知。
如果启用了ECN功能,您可以禁用它:
netsh interface tcp set global ecncapability=disabled
不需要重新启动。可能需要,您知道要更改什么吗?我已经被这个问题困扰了2天了,所以我真的厌倦了。要么发送一些可能包含数据长度的标题,要么在数据中附加一些唯一的序列来标记它的结束。在服务器进程中,这需要知道服务器应该何时结束读取。在其他回答中也实施usr的建议。或者只需先进行单向传输,这样您就可以锁定问题。为了避免复杂性,您可以在不同的端口上读写,如果这对您来说是可行的
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send.
netsh interface tcp set global ecncapability=disabled