c# - 如何在 C# 中有效地确定套接字的状态?

标签 c# sockets

我有一个从客户端接收数据的服务器,我希望能够确定套接字是否仍然连接。

我正在使用以下函数来确定状态( source ):

bool SocketConnected(Socket s)
{
    bool part1 = s.Poll(1000, SelectMode.SelectRead);
    bool part2 = (s.Available == 0);
    if (part1 && part2)
        return false;
    else
        return true;
}

但是,当 RTT(服务器/客户端之间)很高(~300 毫秒)并且变化(+ - 60 毫秒)时,我的应用程序“崩溃”。从调试中我发现这是由于套接字被标识为未连接(SocketConnected()返回false)。但我知道,套接字仍然连接,因为我可以看到客户端流式传输从服务器请求的内容,并且服务器接收由 Wireshark 捕获的数据。

我应该增加轮询的时间(但我不想阻止其他操作)还是将 Socket.Connected 属性与 SocketConnected() 一起使用?在不稳定的环境中确定套接字状态的最有效方法是什么?

最佳答案

不幸的是,您找到并引用的问题和答案充满了糟糕的建议,并且没有什么真正有 build 性的问题可以说。面向连接的协议(protocol)(如 TCP)专门设计用于尽可能长时间地延迟错误,以尽可能多地解决潜在的间歇性传输问题(网络电缆被拔出、无线连接被重置等),以尽量减少这些问题的影响在实际连接上。

对所引用问题的每一个答案都会破坏这一一般策略,或者未能以有用的方式解决问题,或者两者兼而有之。

处理这种情况的唯一正确方法是假设套接字处于您期望的连接状态(基于您自己的代码的操作),同时确保您的代码在每个适当的使用点都有异常处理的 socket 。没有其他办法。

你可以看看Connected属性(property),但这不会告诉你任何有用的东西。检查属性后,套接字可能会在一纳秒内转换为未连接状态。您也不应该使用基于“选择”的方法,例如 Poll()。 ,因为这些效率低下并且不随连接数扩展。

每个联网程序都可以成功使用异步 I/O。如果程序有 GUI(例如 Winforms、WPF 等),那么您甚至可以这样做,同时仍然在 UI 线程中进行所有实际数据处理(这让您不必太担心多线程问题......使用现代 async/await 成语会更好,但您也可以只使用“老派”技术,如 Control.BeginInvoke()Dispatcher.InvokeAsync() )。

因此,遵循这些准则,套接字的连接性以任何有意义、有趣的方式改变状态的唯一时间是当这种情况有意发生时,然后通过正常处理优雅关闭来检测,即读取操作以零字节完成结果,或者由于错误而发生,在这种情况下,您的异常处理将检测到意外断开的状态。

如果没有适当的异常处理,您将无法成功编写无缺陷的网络 I/O 代码,因此只有依赖该异常处理来处理所有异常情况才有意义。

关于c# - 如何在 C# 中有效地确定套接字的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58938811/

相关文章:

c# - 在 C# 中,是否保证任何给定线程都会看到另一个线程对引用类型变量的值所做的更新?

System.Type 的 C# 反序列化从加载的程序集中抛出类型

c# - 通过 Lambda 表达式对 List<Object> 进行排序

c# - 如何快速删除多个文件

c++ - 设置套接字选项以减少 tcp 段之间的时间延迟

c# - 为什么套接字的另一侧不关闭套接字? (关闭等待)?

c# - asp.net MVC 验证出错时如何保留值?

c - 当我用套接字传输结构时,我应该考虑字节顺序吗

Java OutputStream 仅在关闭时刷新数据

关闭客户端中的套接字会使 nodejs 服务器崩溃