c# - .Net Socket 不响应远程断开连接?

标签 c# .net sockets tcpclient

我正在编写一个小型 (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 TcpClientStream,处理TcpClient确实不处理 Stream,因此您需要手动执行此操作,之后所有资源都将被释放(在 GC 之后)。

关于c# - .Net Socket 不响应远程断开连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9683074/

相关文章:

c# - 如何使用 MVVM 根据 Canvas 大小居中形状

c# - .net 4.5 是否支持 NFC Proximity API

c# - 是否可以将此代码的第二部分用于存储库模式和泛型

c# - 使用第三方库(带反射)较旧 .NET 版本的 .NET 应用程序

java - ServerSocket 连接问题

python - 我无法弄清楚我的 Python Socket 错误

C# 使用 BouncyCaSTLe 使用 RSA 对数据进行签名

c# - Json.NET 反序列化 Dictionary<uint, T> 并执行转换

c# - 锁定语句 C#

linux - 发送十二个数据包后 PF_UNIX 套接字阻塞