[英]How can I implement a threaded UDP based server in Java?
如何在Java中實現基於線程的UDP服務器?
基本上我想要的是將多個客戶端連接到服務器,並讓每個客戶端都有自己的線程。 唯一的問題是,我不知道如何檢查客戶端是否正在嘗試連接到服務器並為其生成新線程。
boolean listening = true;
System.out.println("Server started.");
while (listening)
new ServerThread().start();
在這種情況下,服務器將生成新線程,直到內存不足為止。 這是ServerThread的代碼(我想我需要一種機制,在客戶端嘗試連接之前停止創建ServerThread。
public ServerThread(String name) throws IOException
{
super(name);
socket = new DatagramSocket();
}
所以Java編程的父親請幫忙。
這種設計在一定程度上取決於每個完整的UDP“對話框”是否只需要一個請求和立即響應,無論是單個請求還是具有重傳的響應,或者是否需要處理大量數據包每個客戶。
我寫的RADIUS服務器有單個請求+重傳模型,並為每個傳入的數據包生成一個線程。
收到每個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);
}
}
由於UDP是一種無連接協議,為什么需要為每個連接生成一個新線程? 當您收到UDP數據包時,您可能會生成一個新線程來處理收到的消息。
UDP連接與TCP連接不同。 它們不會保持活動狀態,這就是UDP的設計。
下一個代碼塊的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() );
}
}
}
你看過Apache Mina項目了嗎? 我相信即使其中一個例子也會向您介紹如何使用它設置基於UDP的服務器。 如果這是一個真正的產品,我不建議嘗試從頭開始提出自己的實現。 您將需要使用庫來完成此操作,因此您不是每個連接使用一個線程,而是使用線程池。
我真的沒有看到需要。
這是學校的事嗎?
如果需要跟蹤客戶端,則應該具有每個客戶端的本地表示形式(服務器上的客戶端對象)。 它可以處理您需要做的任何客戶特定的事情。
在這種情況下,您需要能夠找出發送消息的客戶端。 (使用消息中的信息。)您可以將客戶端保留在地圖中。
最有效的方法可能是在主線程中進行所有處理,除非需要做的任何事情可以“阻止”等待外部事件(或者如果某些應該發生的事情可能需要很長時間而某些事情很短。 )
public class Client {
public void handleMessage(Message m) {
// do stuff here.
}
}
如果需要,客戶端對象可以在handleMessage()中啟動新線程。
您不應該啟動多個服務器線程。
服務器線程可以做到:
while(running) {
socket.receive(DatagramPacket p);
client = figureOutClient(p);
client.handleMessage(p);
}
如果沒有特定於客戶端的事情需要關注,只需閱讀消息並在它們到達時處理它們,在一個線程中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.