我正在做一些基本的Socket消息传递。我有一个运行良好的例程,但是在负载下存在问题。
我正在使用UDP来执行无连接的SendTo,基本上执行类似ping操作,以查看我的任何侦听器是否在局域网上。理想情况下,我只会使用广播地址,但无线路由器似乎不会转发我的广播。我的工作是迭代子网上的所有IP并将我的数据克发送到每个IP。其他PC正在收听,如果他们收到消息,他们会回复,这就是我让Peers找到对方的方式。以下是循环中的代码,它将数据gram发送到子网中的每个IP。
string msgStr = "some message here...";
byte[] sendbuf = Encoding.ASCII.GetBytes(msgStr);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Blocking = true;
socket.SendTo(sendbuf, remoteEndPt);
//socket.Close();
这是有效的,但是当子网范围很大时,比如255.255.0.0(意味着要迭代~60,000个IP),我最终会得到一个错误代码为“10022”的SocketException,意思是“无效的参数”。在大约10,000次成功发送之后,这往往会发生,然后我开始看到这个错误。此外,我在工作中使用的路由器处理它并且可能是一个高功率路由器,但是我实验室中的廉价路由器是产生错误的路由器。
如果我在捕获SocketException之后等待一段时间并且在恢复循环之前它通常会恢复,但最终我会再次收到错误。
我认为发生的事情是路由器上的缓冲区已满,我无法再发送数据。工作中质量较高的人可以处理它,但廉价的人却陷入困境。听起来有道理吗?
几个问题:
1)以无连接方式使用SendTo时,是否需要在Socket上调用Close()?
我没有看到调用Close()的任何好处,但是当我调用Close()时,它会严重减慢我的迭代速度(我上面已经注释掉它因为它确实减慢了很多事情)。这有意义吗?
2)有没有办法告诉我在尝试发送更多数据之前应该等待?仅仅捕获异常并不正确,我仍然不知道它的原因是什么。
谢谢,J。
答案 0 :(得分:2)
我不确定那只是路由器,但我怀疑你在操作系统中遇到了一些限制......
您每次发送时都有Socket
创建的原因吗?
只需重复使用它......
无论如何,根据http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx,最好在Shutdown()
上拨打Close()
然后Socket
...也许不是每次发送,而是每255个IP或所以...
结帐UdpClient
- 这可以使实施更容易/更健壮
编辑 - 根据评论:
如果你想要一个Socket重用“缓存”...例如,这将确保每256次检查只使用一个特定的Socket ......
// build/fill your Socket-Queue for example in the con
class SocketExample
{
Queue<Socket> a = new Queue<Socket>();
SocketExample ()
{
int ii = 0, C = 256;
for (ii = 0; ii < C; C++)
{
a.Enqueue (new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp));
}
}
// in your function you just dequeue a Socket and use it,
// after you are finished you enqueue it
void CheckNetIP (some parameters...)
{
Socket S = a.Dequeue();
// do whatever you want to do...
// IF there is no exception
a.Enqueue(S);
}
}