Java UDP服务器,并发客户端

时间:2013-01-25 06:45:37

标签: java sockets udp

以下代码是否足以接受并发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);
}

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

如果数据包进入您的网络接口(想象在拥塞的无线信道上丢失数据包),它们将被传递并且将调用阻塞方法socket.receive(p)。如果由于两个客户端同时发送而导致信道上的数据包冲突,则您将无法获得这两个数据包中的任何一个。但这很可能是不可能的,因为网络接口的访问技术将负责这一点,检查 CSMA/CACSMA/CD

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

修改 Description of INTEL's TX and RX descriptors

答案 2 :(得分: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