为了开发一次可以处理最多'x'个客户端的udp服务器,我有两个选择:
当服务器启动时,如果所有'x'客户端都处于活动状态,则会立即创建'x'个线程,而不会进行任何操作。
第二个选项是当服务器启动时,它等待客户端的请求,并且当来自特定客户端的请求到达时,只有一个线程被spwaned来为该客户端提供服务。 如果特定客户端发生故障,则还会删除专用于该特定客户端的线程。
在选项#1中,即使只连接了1个客户端,也会在开始时创建'x'个线程数,只有当线程被利用时,所有剩余的'x-1'线程才会被挂起。
在选项#2中,似乎我将面临连续线程创建和开销的开销。删除。
我决定使用选项#2来实现我的apppication,但如果我的选择是对的,我仍然感到困惑。
如果我错了,请帮助我。
答案 0 :(得分:2)
通过实现线程池来使用两者的组合。创建一个最初为空的线程池,或者包含许多初始挂起的线程,您的选择。当新客户端“连接”并且未超过允许的客户端的最大数量时,请检查池是否具有可用线程。如果是这样,请重新使用它。如果没有,请创建一个新线程。当客户端“断开连接”时,将线程放回池中并暂停它。如果给定的线程在池中停留一段时间,请删除并销毁它。
答案 1 :(得分:1)
在线程运行时考虑上下文切换的开销。在四核CPU上使用三千个线程将比在同一个四核CPU上使用四到八个线程带来更多的开销。考虑三千个线程在堆栈分配方面将使用的资源,而不是四到八个线程。
在静态,预定或用户可配置的线程数上处理尽可能多的非阻塞套接字更有意义。
答案 2 :(得分:1)
选项3 - 可以根据需要增加和减少的线程池,或者理想情况下,根本不增加和减少。
答案 3 :(得分:1)
您所说的有点困惑,或者可能需要更多信息。请记住,UDP客户端不要连接它们只是发送数据包,并且不保证这些数据包按它们发送的顺序到达。
我要做的就是有一个监听UDP套接字等待数据包。您应该通过其IP地址或任何其他方法(例如数据包数据中的ID)维护有效客户端列表。收到数据包后,您可以使用处理客户端请求的函数/线程来处理它。在我看来,你甚至不需要启动新线程,但它取决于收到数据包时服务器要做什么以及处理它需要多长时间。另外,请记住处理请求的函数/线程无法从客户端接收更多数据包(通过同一端口);所有传入的数据包都由服务器线程传递。处理客户端请求的所有功能或线程都是向客户端发送一个或多个UDP数据包来确认请求但是它无法与客户端保持对话,也无法确定客户端是否因为存在而关闭没有永久的开放连接。如果您需要服务器和客户端之间的对话,则需要更改为TCP套接字。
这是代码草案:
ClientRequestThread(DatagramPacket packet)
{
String FromIP = packet.getAddress().getHostAddress();
byte[] data = packet.getData();
// Here you must identify the client, either by its IP address
// or maybe an ID inside the data.
if (TheDataHaveBeenProccessOK)
{
Send a positive acknowledge
}
else
{
Send a negative acknowledge
}
}
ServerThread()
{
DatagramSocket datagramSocket;
try
{
datagramSocket = new DatagramSocket(MyPortNumber);
}
catch (Exception e)
{
// Unable to open the datagram socket.
// Handle it accordingly
return;
}
byte[] buffer = new byte[256]; // change it to your needs
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (YouDontStopMe)
{
try
{
datagramSocket.receive(packet);
// Here you must either call a function or start a thread
// to handle the client request
// depends on what you are going to do with the client's request.
ClientRequestThread(packet);
}
catch (Exception e)
{
// Error reading the socket, handle it accordingly
e.printStackTrace();
}
}
datagramSocket.close();
}