4

下面的代码是否足以接受并发 UDP 传输?更具体地说,如果 2 个客户端同时传输,DatagramSocket 将排队传输并在我调用 receive() 时将它们一一交付,还是只有一个通过?

DatagramSocket socket = new DatagramSocket(port, address);
byte[] buffer = new byte[8192];

while(!disconnect){

    DatagramPacket p = new DatagramPacket(buffer, buffer.length);
    socket.receive(p);
}
4

3 回答 3

3

默认情况下没有排队。客户端可能会重试,直到超时或达到类似情况。UDP 速度很快,但在重负载时,您可能会有无法连接的客户端。

于 2013-01-25T06:49:40.617 回答
0

如果数据包到达您的网络接口(想象在拥塞的无线信道上丢失数据包),它们将通过并socket.receive(p)调用阻塞方法。如果由于两个客户端同时传输而在通道上发生数据包冲突,您将不会收到这两个数据包中的任何一个。但这很可能是不可能的,因为网络接口的访问技术会解决这个问题,检查 CSMA/CACSMA/CD

调用后,socket.receive(p)您应该创建一个新线程来处理数据包本身。这将确保可以在套接字上接收下一个数据包。

编辑: INTEL 的 TX 和 RX 描述符的描述

于 2013-01-25T07:44:30.540 回答
0

一个基本的解决方案是在线程上负责处理许多传入请求(具有您想要的限制),然后将它们交给其他工作程序/请求处理程序线程。这种基本结构与大多数服务器非常相似:主线程负责将请求传递给工作线程。当每个工作线程完成后,您可以更新共享/全局计数器,让主线程知道它可以建立新连接。这将需要同步,但它是一个简洁的抽象。

这是想法:

服务器线程

// Receive Packet
while (true) {
    serverLock.acquire();

    try {
        if (numberOfRequests < MAX_REQUESTS) {
            packet = socket.receive();
            numberOfRequests++;
            requestThread(packet).run();
        } else {
            serverMonitor.wait(serverLock);
        }
    } finally {
        serverLock.release();
    }
}

请求线程

// Handle Packet
serverLock.acquire();

try {
    if (numberOfRequests == MAX_REQUESTS){         
        numberOfRequests--;
        serverMonitor.pulse();
    }
} finally {
    serverLock.release();
}

这只是为了让您了解可以从什么开始。但是当您掌握了它的窍门后,您将能够进行优化和增强以确保同步完全正确。

一种特殊的增强,也适用于有限数量的请求,称为ThreadPool

于 2017-03-24T06:20:55.203 回答