如何在 Java 中实现基于线程 UDP 的服务器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/773121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I implement a threaded UDP based server in Java?
提问by
How can I implement a threaded UDP based server in Java ?
如何在 Java 中实现基于线程 UDP 的服务器?
Basically what I want, is to connect multiple clients to the server, and let each client have his own thread. The only problem is, that I don't know how to check if a client is trying to connect to the server and spawn a new thread for it.
基本上我想要的是将多个客户端连接到服务器,并让每个客户端都有自己的线程。唯一的问题是,我不知道如何检查客户端是否正在尝试连接到服务器并为其生成一个新线程。
boolean listening = true;
System.out.println("Server started.");
while (listening)
new ServerThread().start();
In this case the server will spawn new threads until it runs out of memory. Here's the code for the ServerThread ( I think I need here a mechanism that stalls the creation of the ServerThread until a client tries to connect.
在这种情况下,服务器将产生新线程,直到内存耗尽。这是 ServerThread 的代码(我想我需要一种机制来阻止 ServerThread 的创建,直到客户端尝试连接。
public ServerThread(String name) throws IOException
{
super(name);
socket = new DatagramSocket();
}
So fathers of Java programming please help.
所以请Java编程的父亲们帮忙。
采纳答案by Alnitak
The design for this to a certain extent depends on whether each complete UDP "dialog" just requires a single request and immediate response, whether it's a single request or response with retransmissions, or whether there'll be a need to process lots of packets for each client.
对此的设计在一定程度上取决于每个完整的 UDP“对话”是否只需要一个请求和立即响应,是单个请求还是带有重传的响应,或者是否需要处理大量数据包每个客户。
The RADIUS server I wrote had the single request + retransmit model and spawned a thread for each incoming packet.
我编写的 RADIUS 服务器具有单个请求 + 重传模型,并为每个传入数据包生成一个线程。
As each DatagramPacket
was received it was passed to a new thread, and then that thread was responsible for sending back the response. This was because the computation and database accesses involved in generating each response could take a relatively long time and it's easier to spawn a thread than to have some other mechanism to handle new packets that arrive whilst old packets are still being processed.
当每个DatagramPacket
接收到时,它被传递到一个新线程,然后该线程负责发回响应。这是因为生成每个响应所涉及的计算和数据库访问可能需要相对较长的时间,并且生成线程比使用其他机制来处理到达而旧数据包仍在处理中的新数据包更容易。
public class Server implements Runnable {
public void run() {
while (true) {
DatagramPacket packet = socket.receive();
new Thread(new Responder(socket, packet)).start();
}
}
}
public class Responder implements Runnable {
Socket socket = null;
DatagramPacket packet = null;
public Responder(Socket socket, DatagramPacket packet) {
this.socket = socket;
this.packet = packet;
}
public void run() {
byte[] data = makeResponse(); // code not shown
DatagramPacket response = new DatagramPacket(data, data.length,
packet.getAddress(), packet.getPort());
socket.send(response);
}
}
回答by Peter D
Since UDP is a connectionless protocol, why do you need to spawn a new thread for each connection? When you receive a UDP packet maybe you should spawn a new thread to take care of dealing with the message received.
既然 UDP 是无连接协议,为什么每次连接都需要产生一个新线程呢?当您收到 UDP 数据包时,您可能应该创建一个新线程来处理收到的消息。
UDP connections are not like TCP connections. They do not remain active and such is the design of UDP.
UDP 连接不像 TCP 连接。它们不会保持活动状态,这就是 UDP 的设计。
The handlePacket() method of this next code block can do whatever it wants with the data received. And many clients can send multiple packets to the same UDP listener. Maybe it will help you.
下一个代码块的 handlePacket() 方法可以对接收到的数据做任何它想做的事情。并且许多客户端可以向同一个 UDP 侦听器发送多个数据包。也许它会帮助你。
public void run() {
DatagramSocket wSocket = null;
DatagramPacket wPacket = null;
byte[] wBuffer = null;
try {
wSocket = new DatagramSocket( listenPort );
wBuffer = new byte[ 2048 ];
wPacket = new DatagramPacket( wBuffer, wBuffer.length );
} catch ( SocketException e ) {
log.fatal( "Could not open the socket: \n" + e.getMessage() );
System.exit( 1 );
}
while ( isRunning ) {
try {
wSocket.receive( wPacket );
handlePacket( wPacket, wBuffer );
} catch ( Exception e ) {
log.error( e.getMessage() );
}
}
}
回答by Elijah
Have you looked at the Apache Minaproject? I believe even one of its examples takes you through how to setup an UDP-based server with it. If this for a real product, I would not recommend trying to come up with your own implementation from scratch. You will want to use a library to accomplish this so you are notusing one thread per connection, rather a thread pool.
你看过Apache Mina项目吗?我相信即使是它的一个示例也会带您了解如何使用它设置基于 UDP 的服务器。如果这是一个真正的产品,我不建议尝试从头开始提出自己的实现。您将需要使用库来完成此操作,因此您不会为每个连接使用一个线程,而是使用一个线程池。
回答by KarlP
I don't really see the need.
我真的看不出有必要。
Its a school thing right?
这是学校的事情吧?
If you need to keep track of the clients, you should have a local representation of each client (a Client object on your server). It can take care of whatever client-specific things you need to do.
如果您需要跟踪客户端,您应该拥有每个客户端的本地表示(服务器上的 Client 对象)。它可以处理您需要做的任何特定于客户的事情。
In that case You need to be able to find out from which client the message was sent from. (using information from the message.) You can keep the clients in a map.
在这种情况下,您需要能够找出消息是从哪个客户端发送的。(使用消息中的信息。)您可以将客户端保留在地图中。
The most effective way is probably to do all handling in the main thread, unless whatever that needs to be done can "block" waiting for external events (or if some things that's supposed to happen might take a long time and some a very short.)
最有效的方法可能是在主线程中完成所有处理,除非需要做的任何事情都可以“阻塞”等待外部事件(或者如果某些应该发生的事情可能需要很长时间,而有些则很短。 )
public class Client {
public void handleMessage(Message m) {
// do stuff here.
}
}
The client object can perhaps start a new thread in handleMessage() if neccesary.
如果需要,客户端对象也许可以在 handleMessage() 中启动一个新线程。
You shouldn't start multiple server threads.
您不应该启动多个服务器线程。
The server thread can do:
服务器线程可以执行以下操作:
while(running) {
socket.receive(DatagramPacket p);
client = figureOutClient(p);
client.handleMessage(p);
}
If there are no client-specific things to care about, just read the messages and handle them as they arrive, in one thread.
如果没有客户端特定的事情需要关心,只需在一个线程中读取消息并在它们到达时处理它们。