套接字的 sendTo() 不会发送任何数据包,除非我明确休眠线程

本文关键字:数据包 非我 线程 休眠 任何 sendTo 套接字 | 更新日期: 2023-09-27 18:06:22

这些天我面临着一种非常奇怪的行为。我正在Visual Studio 2015上开发一个C#程序,该程序将udp帧发送到远程主机。我有以下代码:

Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
byte[] char_send = new byte[1] { Convert.ToByte('l') };
soc.SendTo(char_send, send_IPEndPoint);
EndPoint listen_EndPoint = soc.LocalEndPoint;
IPEndPoint listen_IPEndPoint = (IPEndPoint)soc.LocalEndPoint;
soc.Close();

什么也没发生。在Wireshark上看不到任何东西。

但是,如果我在 sendTo(( 之后立即将线程休眠 1 毫秒,则帧会正确发送。

Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
byte[] char_send = new byte[1] { Convert.ToByte('l') };
soc.SendTo(char_send, send_IPEndPoint);
Thread.Sleep(1);
EndPoint listen_EndPoint = soc.LocalEndPoint;
IPEndPoint listen_IPEndPoint = (IPEndPoint)soc.LocalEndPoint;
soc.Close();

怎么可能?我显然在这里错过了一些东西,我只是想不通是什么。多谢。

套接字的 sendTo() 不会发送任何数据包,除非我明确休眠线程

问题是您在调用SendTo()后立即关闭Socket

Socket只是逻辑结构,实际发生的是将要发送的数据复制到系统缓冲区,然后操作系统负责通过网络实际发送位。由于您正在关闭释放它并释放非托管资源的Socket,因此您告诉操作系统释放与释放尚未通过网络实际发送的数据的Socket相关的资源。

一种解决方法可能是添加 ACKnowledgement - 这样接收器在收到您的数据报后就会向您发送一个小数据报 - 然后您可以关闭套接字。事实上,由于UDP不保证交付,您可能无论如何都想这样做。或者,如果您只想触发并忘记 Thread.Sleep(( 也可以工作。

PS:正确的术语是引用用户的UDP数据包时的"数据报"。"帧"倾向于用于以太网级数据包。