以下代码是否足以接受并发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);
}
答案 0 :(得分:3)
默认情况下没有排队。客户端可能会重试,直到达到超时或类似时间。 UDP很安静,但在负载很重的情况下,您的客户端可能无法连接。
答案 1 :(得分:0)
如果数据包进入您的网络接口(想象在拥塞的无线信道上丢失数据包),它们将被传递并且将调用阻塞方法socket.receive(p)
。如果由于两个客户端同时发送而导致信道上的数据包冲突,则您将无法获得这两个数据包中的任何一个。但这很可能是不可能的,因为网络接口的访问技术将负责这一点,检查
CSMA/CA或CSMA/CD
在调用socket.receive(p)
之后,您应该创建一个新线程来处理数据包本身。这将确保可以在套接字上接收下一个数据包。
答案 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。