我正在一台具有四个网络适配器的计算机上创建四个套接字,并将每个套接字绑定到一个网络适配器。
网络适配器 1 位于 192.168.100.10。套接字 1 绑定到网络适配器 1
网络适配器 2 的地址为 192.168.100.20。套接字 2 绑定到网络适配器 2
网络适配器 3 的地址为 192.168.100.30。套接字 3 绑定到网络适配器 3
网络适配器 4 的地址为 192.168.100.40。套接字 4 绑定到网络适配器 4
以下是我使用的代码:
Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipEndPoint = new IPEndPoint(localIP, 0);
EndPoint ep = (EndPoint)ipEndPoint;
每个网络适配器都有一个本地网络,其中一台不同的设备的 IP 地址为 192.168.100.1。我向该设备发送 SNMP(UDP 协议)请求数据。
套接字 1 在绑定到 192.168.100.10 网络适配器 1 时向设备 1 (192.168.100.1) 发送数据
套接字 2 在绑定到 192.168.100.20 网络适配器 2 时将数据发送到设备 2 (192.168.100.1)
套接字 3 在绑定到 192.168.100.30 网络适配器 3 时将数据发送到设备 3 (192.168.100.1)
套接字 4 在绑定到 192.168.100.40 网络适配器 4 时向设备 4 (192.168.100.1) 发送数据
EndPoint remote = (EndPoint)new IPEndPoint(peer.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,0);
IPEndPoint ipEndPoint = new IPEndPoint(_localIP, 0);
EndPoint ep = (EndPoint)ipEndPoint;
_socket.Bind(ep);
byte[] inbuffer = new byte[64 * 1024];
_socket.SendTo(buffer, bufferLength, SocketFlags.None, (EndPoint)netPeer); //bufer has the snmp request
Thread.Sleep(4000);
if (_socket.Available > 0)
{
recv = _socket.ReceiveFrom(inbuffer, ref remote);
}
_socket.Close();
上面的代码创建了四个线程,每个套接字始终在发送和接收数据。发送一个数据请求和响应后,套接字将关闭。为下一个 SNMP 请求创建一个新的。套接字阻塞是正确的。 TTL 默认为 128。
这适用于 90% 的 SNMP 请求,但是对于一组特定的 SNMP 请求 (10%),我发现 SNMP
_socket.Available
始终返回 0。疯狂的是,我可以看到 SNMP 响应在 Wireshark 中返回。我确实在 Wireshark 中看到了响应,并且当 _socket.Available > 0
或 _socket.Available == 0
时,原始 Wireshark 数据没有差异。这 10% 的 SNMP 请求有时会起作用,但并非总是有效。我确实两次在 Wireshark 中看到相同的数据。
我已经尝试了很多故障排除,但最重要的是,我在 Wireshark 中看到了数据响应,但代码仍然显示
_socket.Available == 0
。我在想也许其他套接字之一正在窃取数据?即使套接字绑定到另一个网卡也可能吗?
我还尝试了下面的代码,其中我忽略了
_socket.Available
并使用超时而不是睡眠。我得到了同样的结果。
IPEndPoint ipEndPoint = new IPEndPoint(_localIP, 0);
EndPoint ep = (EndPoint)ipEndPoint;
_socket.Bind(ep);
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, timeout);
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, timeout);
_socket.SendTo(buffer, bufferLength, SocketFlags.None, (EndPoint)netPeer);
recv = _socket.ReceiveFrom(inbuffer, ref remote);
我打算一次只运行一个套接字,但这会减慢程序速度。
我还打算尝试两个套接字,一个用于发送,一个用于接收,看看是否可以解决问题。
有什么想法吗?我实际上使用了 SnmpSharpNet 库中的很多代码。如果您对此问题有任何见解或任何建议,请告诉我。
使用 UDP 及时接收数据包以清除接收缓冲区至关重要,否则可能会因缓冲区已满而导致丢包。如果您读取它们的速度不够快,则可能会淹没接收缓冲区。 10% 的掉率听起来很多,但这可能是由于您的代码所致。
在你的代码中我看到 Thread.Sleep(4000)
您应该确保数据包不会在接收缓冲区中等待。睡4秒有点多了。自从我做了很多 TCP/UDP 编码以来,已经有很多年了,但我记得足够多,知道当我为每个接收器使用单独的线程并在读取时阻塞时,我使用 UDP 获得了最好的结果,这样操作系统就负责唤醒我的数据准备好后立即线程。
至少将 Thread.Sleep(4000) 降低到亚秒级(尝试 250 或更少),看看是否有所改善。如果是这样,那么您就走在正确的道路上。可以增加操作系统级别的接收缓冲区大小,但这通常仅适用于极端情况,如果您的用户代码写得很好,则不需要这样做。
此外,我认为没有理由不断打开/关闭套接字。保持打开状态。
这里的问题原来是路由问题,因为另一端有类似的网络,导致 PC 变得混乱。