3

背景:

我在一台机器上运行 TCP 服务器,多个客户端在通过 TCP 连接的不同机器上,我正在使用 Wireshark 监视网络流量,以及从我的服务器应用程序中以及通过 System.Net 上的 System.Diagnostics 跟踪侦听器进行日志记录. 详细模式下的套接字。

问题:

由于一些意外断开连接提示检查我的日志,我看到一些非常奇怪的行为。根据服务器应用程序日志和 System.Diagnostic 输出日志,我的服务器正在使用开始/结束发送向客户端发送一个 4 字节数据包。BeginSend 完成,EndSend 也完成,表示它成功发送了 4 字节数据包。

但是,当我查看 Wireshark 日志时,该数据包从未出现过。我在服务器机器上运行 Wireshark,所以数据包应该没有理由出现在我的服务器和跟踪日志中,但不会出现在同一台机器上的 Wireshark 日志中。

此外,在所谓的成功发送数据包后不久(约 30 秒后)发生意外断开连接,这是由我的服务器的 EndReceive 方法上的 SocketException 引起的。但是在尝试从服务器发送之间的时间段内,服务器正在确认从客户端接收到的数据包,所以我知道连接仍然处于活动状态。

有没有人有类似的经历,或者知道一个错误或可能导致这种情况的东西?

我不愿意认为这发生在套接字级别,TCP 说我的数据包是在它甚至从未到达网络时发送的,这意味着我不能依赖 TCP 作为可靠的传输(当然是 TCP 的重点)。

日志样本

从我的服务器应用程序:

    2011-09-07 10:41:38,812 Attempting to send Packet (BeginSend - 4 bytes)
    2011-09-07 10:41:38,812 Sent Packet (EndSend - 4 bytes)

从 System.Diagnostics 跟踪日志:

System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::BeginSend()
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [0980] Data from Socket#19699911::PostCompletion
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [0980] 00000000 : 02 04 00 00                                     : ....
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::EndSend(OverlappedAsyncResult#44209720)
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::EndSend()   -> 4#4
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::BeginSend()     -> OverlappedAsyncResult#44209720
    DateTime=2011-09-07T17:41:38.8125000Z

我也会粘贴 Wireshark 日志,但基本上当时该设备的接口上没有任何注册,除了来自客户端的数据包和来自服务器的相应确认。

编辑: 根据要求,这是发送的代码(由于空间和其他原因而缩短)。很简单,没有太多可能出错的地方。

在我的 BeginSend 方法中:

socket.BeginSend(data, 0, data.Length, SocketFlags.None, EndSend, state);

在我的 EndSend 方法中:

bytesSent = socket.EndSend(ar);

注意:这不是我第一次参加牛仔竞技表演,正如他们所说的那样……在过去的 15 年里,我一直在使用 TCP 套接字编写服务器和客户端,以前从未经历过这种情况。

此外,我使用的 .NET 版本是 4.0 ......如果有任何相关性的话。

帮助!

4

4 回答 4

0

如果可以忽略其限制,您是否可以重写应用程序以使用TcpClient而不是Socket? 如果您的应用程序无论如何都绑定到 TCP/IP,至少对于这个特定的套接字,您不妨使用抽象——它可能会有所帮助。此外,您可以尝试使用EndSend(IAsyncResult, SocketError)重载来查看SocketError对象是否包含任何有用的内容。

如果这些软件调整都没有帮助,我必须同意问题必须低于 .NET 软件级别,即防火墙软件(或硬件)、防病毒等。

于 2011-09-07T20:12:22.057 回答
0

我在 .NET 中使用套接字编程时遇到的一个问题与垃圾收集有关。我的代码是在我的方法中创建一个套接字并分配给一个局部变量,而不是分配给一个成员变量。然后套接字被垃圾收集,导致SocketException. 显然,做 aBeginSend不足以保存对该套接字的引用。

将套接字移动到成员变量为我解决了这个问题。希望这与您遇到的问题有关。

于 2011-09-07T20:01:17.333 回答
0

我不愿意认为这发生在套接字级别,TCP 说我的数据包是在它甚至从未到达网络时发送的,这意味着我不能依赖 TCP 作为可靠的传输(当然是 TCP 的重点)。

这种说法是不正确的。仅仅因为您成功写入套接字并不意味着数据已被客户端接收甚至离开您的机器。这只是意味着它已成功写入内部 TCP/IP 缓冲区。TCP/IP 将以它认为合适的多或少的块/帧发送该数据。如果您发送的数据很小,则尤其如此,TCP/IP 将延迟尝试将其他数据聚合到帧中。

如果您在 Wireshark 中没有看到它,那么您可能没有在正确的接口上侦听,没有设置过滤器,或者某种防火墙阻止您发送数据。看看任何防病毒或其他分层服务提供商,看看谁可以进入那里。

于 2011-09-07T20:06:03.950 回答
0

那么这个问题是很久以前的了,所以你可能已经继续......如果其他人有同样的问题,你可能想检查 Windows 的内存压力保护是否可能会启动。这将导致数据包在以下情况下被丢弃有多个同时连接,这就是您所看到的。

您可以尝试的另一个实验是暂时关闭服务器计算机上的防火墙。这也将关闭所有这些保护机制(如果我没记错的话),如果一切正常,你知道其中之一就是罪魁祸首。

于 2013-09-03T02:42:09.670 回答