循环中的C#Socket.SendTo最终导致SocketException(取决于路由器)




我正在做一些基本的Socket消息。我有一个运行良好的例程,但在负载下出现了问题。

我用UDP做一个无连接的SendTo,基本上是做一个类似ping的操作,看看我的侦听器是否在局域网上。理想情况下,我只会使用广播地址,但无线路由器似乎不会转播我的广播。我的工作是迭代子网上的所有IP,并将我的数据发送到每个IP。其他电脑正在监听,如果他们收到消息,他们会回复,这就是我让同行们找到彼此的方式。这是循环中的代码,它将数据报发送到子网中的每个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(意味着要迭代约60000个IP(,我最终会得到一个SocketException,错误代码为"10022",意思是"无效参数"。这种情况往往发生在大约10000次成功发送之后,然后我开始看到这个错误。此外,我在工作中使用的路由器可以处理它,可能是一个高功率路由器,但我实验室里的廉价路由器就是产生错误的路由器。

如果我在捕捉到SocketException之后和恢复循环之前投入一段等待时间,它通常会恢复,但最终我会再次出现错误。

我想发生的事情是路由器上的缓冲区已经满了,我无法再发送数据了。工作中质量较高的人可以应付,但价格较低的人会陷入困境。这听起来合理吗?

几个问题:

1( 当以无连接方式使用SendTo时,我是否需要在套接字上调用Close((?

我还没有看到调用Close((有任何好处,但当我调用Close时,它会严重减慢我的迭代速度(我在上面评论了它,因为它确实会减慢很多速度(。这有道理吗?

2( 有没有办法告诉我在尝试发送更多数据之前应该等待?仅仅抓住异常似乎是不对的,我仍然不知道它的原因是什么。

谢谢,J.

我不确定这只是路由器,但我怀疑你在操作系统中也遇到了一些限制。。。

您每次发送都创建Socket的原因是什么?重复使用它…

无论如何,根据http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx在Socket上调用Shutdown()然后调用Close()是个好主意。。。也许不是每次发送,而是每255个IP左右…

检查UdpClient-这可以使实现更容易/更强大的

编辑-根据注释

如果你想要一个套接字重用"缓存"。。。例如,这将确保每256次检查只使用一个特定的套接字。。。

// 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); 
    }
}

最新更新