我正在编写一个小型 (C#) 客户端应用程序,它使用 TCP/IP 连接将数据发送到远程服务器。我正在使用标准的 .Net TcpClient 对象,并且希望在客户端保持连接打开,因为我会定期向服务器提交数据包。但是,服务器可能会关闭连接,在这种情况下,我需要知道在发送下一个数据包之前重新连接。
使用 Wireshark,当服务器终止连接时,我可以(仅)看到以下对话:
server >>> FIN, ACK<br/> ACK <<< client
我没有看到的是我的客户端用它自己的 FIN 响应,以完成连接关闭。结果是我的客户端程序在发送下一个数据包后才发现连接断开了。
有什么方法可以设置 TcpClient 或其底层套接字以完成断开连接,并提供一些反馈以便我的客户端代码知道在发送下一个数据包之前重新连接?
添加 以回应以下评论: 我的发送代码非常简单 - 维护 TcpClient 和 NetworkStream 成员变量的对象有一个包含(本质上)以下内容的成员函数:
bool sent = false;
byte[] buffer = Encoding.UTF8.GetBytes(dataString);
while (!sent)
{
try
{
m_outStream.Write(buffer, 0, buffer.Length);
sent = true;
}
catch (Exception ex)
{
if (m_outStream != null) { m_outStream.Dispose(); }
m_client = new TcpClient(AddressFamily.InterNetwork);
m_client.Connect(ipAddress, ipPort);
m_outStream = m_client.GetStream();
}
}
随着 m_client 和 m_outStream 的初始化,每次只执行一次。然后使用 Wireshark 我可以看到服务器发送了一个带有标志的数据包 FIN, ACK
客户端响应ACK
.
下次我调用我的函数时,数据用PSH, ACK
发送出去, 服务器响应 RST, ACK
但不读取传入的数据。客户没有提出异常。
然后我第二次调用我的函数,并引发异常导致重新启动连接。
最佳答案
一般来说,您应该能够在 TcpCient
实例上使用 Connected
属性:
看这里:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx
但是:
Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions.
尝试以下操作以确保 Connected
标志保持最新状态:
var tcpClient = new TcpClient ();
tcpClient.Connect();
var stream = tcpClient.GetStream();
// buffer size need to be > 0
int[] buffer = new int[1];
stream.Read(buffer, 0, 0);
if(!tcpClient.Connected)
// do something
基于反编译,应该可以从流中读取 0
字节,至少 .NET Framework TcpClient
中没有检查来阻止这种情况。然而,在从框架调用以实际从网络流中读取的外部代码中,它可能不会大声。
确保在完成后同时Dispose
TcpClient
和Stream
,处理TcpClient
确实不处理 Stream
,因此您需要手动执行此操作,之后所有资源都将被释放(在 GC 之后)。
关于c# - .Net Socket 不响应远程断开连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9683074/