[英]UDP client async doesn't close sockets
我正在尝试编写自定义UDP端口嗅探器。 我正在尝试扫描本地网络以查找正在接收数据的UDP端口。也许这是一个非常琐碎的问题,但我被困在这里。 我尝试了很多示例和教程,但找不到合适的解决方案。 我使用以下两种方法成功完成了此操作:
private static int udpListenPort = 1026;
bool flag=false;
public void ReceiveMessages()
{
for (udpListenPort = 1026; udpListenPort< 1200; udpListenPort++)
{
if (flag)
{
messageReceived = false;
IPEndPoint e = new IPEndPoint(IPAddress.Any, udpListenPort);
UdpClient u = new UdpClient(e);
UdpState s = new UdpState();
s.e = e;
s.u = u;
u.BeginReceive(new AsyncCallback(CheckUdpPort), s);
for (int i = 0; i < 5; i++)
{
Thread.Sleep(8);
if (messageReceived)
{
break;
}
}
if (messageReceived)
{
// Updating UI
}
//u.Close(); // I'm trying this but returns an exception
e = null;
u = null;
s = null;
}
}
}
和这个:
public class UdpState
{
public IPEndPoint e;
public UdpClient u;
}
private static void CheckUdpPort(IAsyncResult ar)
{
UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;
Byte[] data = u.EndReceive(ar, ref e);
// Some code to filter the data received
messageReceived = true;
}
我在WPF程序中使用这些方法。 扫描完成后,我尝试再次启动它,此时IDE重新调整以下异常:
IPEndPoint e = new IPEndPoint(IPAddress.Any, udpListenPort);
UdpClient u = new UdpClient(e); //HERE
UdpState s = new UdpState();
“ System.Net.Sockets.SocketException”通常只允许使用每个套接字地址(协议/网络地址/端口)的一种。
我试图关闭每个端口,但是程序在此行中返回以下异常“ System.ObjectDisposedException”:
Byte[] data = u.EndReceive(ar, ref e);
任何帮助将不胜感激。
注意:经过更多尝试,我意识到我只有一个例外:“在以前的扫描中未收到任何数据的UDP端口上,通常只允许使用每个套接字地址(协议/网络地址/端口)。
你有没有尝试过:
u.Client.Shutdown();
u.Client.Close();
而不是:
u.Close();
跟随msdn:
http://msdn.microsoft.com/en-us/library/wahsac9k.aspx
“对于面向连接的协议,建议在调用Close方法之前先调用Shutdown。这可确保在关闭套接字之前,已在连接的套接字上发送和接收所有数据。”
当您直接在套接字上工作时,有点。
UdpClient甚至实现IDisposable
public class UdpClient : IDisposable
意味着您可以在
using(u = new UdpClient(foo)){
//do some stuff
}
然后让让客户端的家伙处理套接字
如果不;
做一个
try{
//do stuff
}
finally{
u.client.shudown();
u.client.close();
}
解决 。 经过更多的研究和艰苦的工作,这是工作结果。 我使用了同步读取,使用超时来丢弃未接收数据的UDP端口。
private void BETAScanNetwork()
{
int contador = 0;
for (int i = 1140; i <= 1160; i++)
{
UdpClient listener = null;
bool incoming = false;
try
{
listener = new UdpClient(i);
var groupEp = new IPEndPoint(IPAddress.Any, i);
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 50);
byte[] data = listener.Receive(ref groupEp);
incoming = true;
listener.Client.Shutdown(SocketShutdown.Both);
listener.Client.Close();
// Managing received data
}
catch (System.Net.Sockets.SocketException e)
{
var excp = e.SocketErrorCode;
if (excp== SocketError.TimedOut)
{
continue;
}
else
{
throw;
}
}
finally
{
if (listener != null && !incoming)
{
listener.Client.Shutdown(SocketShutdown.Receive);
listener.Close();
}
}
}
}
感谢您对@ lord_alek1的关注。
出现原始问题的原因是因为您应该重新使用对象,而不是一直创建一个新对象。 否则,您将收到消息“每个套接字地址仅一种用法”。UdpClient u = new UdpClient(e);
除非您的主线程在threading.thread.sleep(8)的那8毫秒内有更重要的事情要做,否则我什至不会为async ..所困扰,只需使用.receive()来等待/从套接字缓冲区中读取。 并像上面最后一样设置超时时间。 btw thread.sleep的最小长度为8ms到16ms。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.