是否可以接收零字节消息?我的应用程序是一种消息路由器,它接收,检查和发送消息。
我使用Socket.Poll
等待传入的消息。该应用程序工作。正常沟通期间没有问题。
糟糕的事情发生在大约15分钟不活动之后。我注册了套接字可读状态,套接字报告IsConnected = true
和Available = 0
。由于协议要求数据包符合X.690,因此它不知道如何处理零字节消息和崩溃。
由于我不知道这个奇怪的状态意味着什么,我决定忽略这个可能的.NET错误,然后再次进入套接字轮询循环。正如我所料 - 它在那里耐心地等待,但是当我从客户端请求一些活动时 - 我的路由器说了一些关于被强行断开的事情。发生了什么事?
我的应用检查LDAP流量。我被告知LDAP服务器没有超时,我测试了它。他们不会,至少15分钟后不会。我的应用程序(根据我对传输协议的理解)或.NET本身都有问题。
我已经在.NET中发现一个错误,导致Socket.Poll在使用它之前不可靠,然后才能从NetworkStream
和SslStream
读取数据。解决方法是在执行读取之前等待1ms。我的应用程序中没有必要这样做,因为它经过精心设计,只使用同步调用并尽可能少地使用精心同步的线程。我甚至测试过5微秒就足以让它工作,但为了达到完全稳定性,我决定等待整整1毫秒,因为它不会给我的过程带来明显的滞后。我尝试将所有内容与所有内容同步,使其完全单一,在每个可能的代码行上引入等待,除了完全一个且只有确切的位置之外什么都没有 - 直接在注册可读状态和执行Stream.Read()
之间。我在一个月内测试了这个,不知道为什么会发生这种情况,1ms等待解决问题,而不是因为我等了一次崩溃。
所以我不排除.NET本身的另一个错误。还有什么?可能是客户吗?客户端是LDP应用程序。服务器是LDS。全部在我的本地主机上。
收到这样的东西后我该怎么办?断开会话?它不会导致客户端抛出错误消息吗?什么是最重要的 - 它为什么会发生?我的应用程序中的所有套接字都将其超时设置为零(这意味着无限期等待)。
显然会话是Task
,运行方式为LongRunning
。可能会以某种方式超时系统?但如果是这种情况,我怎么能从这项任务中收到IOException
?
我想要实现的是我的应用程序永远不会超时。会话启动时,它必须处于活动状态,直到明确断开连接。我的应用程序正确检测到断开。每个体面的客户端发送一个特殊的数据包,正常,长度非零,意味着"断开请"。但是在这种奇怪的超时情况下 - 除了没有可阅读内容的可读状态之外,我没有发现任何事情。
关于零长度数据包的其他问题的副本:
客户端似乎根本没有断开连接。它看到了活动会话。看起来我的应用程序,而不是客户端丢失了连接。它不在我的代码中,所以它在.NET或Windows中。回答我收到断开请求并没有解决我的问题。我回到了第一个方向。我没有请求断开连接。我希望我的关系能够保持活力,但Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
根本没有帮助。更重要的是,如果我在收到此数据包后尝试断开连接,则客户端会在第一次通信尝试时崩溃,因为此时此功能无法断开连接。我会尝试在断开连接之前通知客户端作为解决方法,但我仍然不知道导致断开请求的原因。这就是我的问题不同的原因。它不是关于零字节数据包的含义,更重要的是我为什么得到它,更多关于如何防止它发生。
关于它如何结束: 当我收到0长度状态时,我发出一个"空数据包"到我的应用程序的另一个端点(让我们称之为B)。然后我的端点A断开连接。在另一个端点B收到"空数据包"之后的几个时钟节拍。并断开连接。当客户端尝试发送另一个请求时,它会正确检测状态,重新连接并执行其操作。没有任何错误报告。工作完美无瑕。我有点意外,因为当我手动断开客户端(即使从任务管理器中删除它的任务)时,它发送了一个特殊的结束会话消息。在这里我收到了不同的东西我知道哪一方要求断开连接并不重要,我只需要关闭插座来处理它。至少它起作用了。