伙计们!我写了简单的服务器客户端(udp)应用程序。现在我正在尝试做一个可以接受很多客户端的服务器。据我所知,我需要创建接受和处理客户端的函数,但我对应用程序的结构感到困惑。你能检查我的应用程序是否有正确的骨架吗?也许你可以给我一些提示或例子。非常感谢您的建议!:)
class MultiServer {
private DatagramSocket serversocket;
public MultiServer() {
try {
this.serversocket = new DatagramSocket(6789);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException {
while(true) {
DatagramSocket serversock = serversocket.accept();
new Thread(new ClientHandler(serversock)).start();
}
}
public static void main(String[] args) {
Server1 server = new Server1();
try {
server.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
private final DatagramSocket clientsocket;
ClientHandler(DatagramSocket sock) {
this.clientsocket = sock;
}
@Override
public void run() {
//receive packet, send msg, get ip, get portnumber ?
}
}
}发布于 2013-04-11 00:47:00
因此,您希望您的服务器能够同时处理多个请求?很好,这是大多数web服务器的工作方式。你必须理解多线程和并发的基本概念。
一个简单的服务器一次只能处理一件事。如果在服务器处理其他事务时收到另一个请求,会发生什么情况?什么都没有,所以应用程序效率不高,而且根本不具备可伸缩性。
如果您还没有在应用程序中使用多线程,并且对并发了解不多,那么现在是尝试一下、阅读Oracle Concurrency Lesson或在线查找教程的好时机,这里有很多教程。
现在,一旦(或者如果)你知道线程是如何工作的,请确保你尽可能地分解你的函数,看看哪些函数可以同时发生。我能想到的Web服务器的一个例子是:
处理该请求的单独线程(或多个线程/线程池
您的结构看起来像是在同一个Runnable中同时接收和处理。无论如何,这只是一个想法,你必须看看哪个更适用于你的应用程序。另外,看看新的Java版本提供的并发工具,Java 6和7提供了许多非常有效的工具(但在我看来也很难理解和使用)。
祝好运!
发布于 2013-04-11 00:44:32
您正在寻找线程池服务器。你开始的方式很好。现在,您只需实现一个Java execution Service来处理请求。线程池有一个固定的线程数。它确实接受你的请求,并将这些请求放入队列中,如果一个请求完成,它就会接受下一个请求。所以你通常不会丢失任何请求。
下面是我做的一个小例子:
public class PoolServer implements Runnable {
private static final int DEFAULT_PORT = 8080;
private static final String CONFIG = "config.xml";
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
protected ExecutorService threadPool = Executors.newFixedThreadPool(100);
protected int serverPort;
public PoolServer() {
// getting the port from the XML
this.serverPort = getPortFromXML();
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
// accepting loop
while (!isStopped()) {
Socket clientSocket = null;
try {
// accept the client
clientSocket = this.serverSocket.accept();
clientSocket.setSoTimeout(2000);
} catch (IOException e) {
if (isStopped()) {
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
this.threadPool.execute(new ThreadHandler(clientSocket));
}
// loop end
// server stopped shut down the ThreadPool
this.threadPool.shutdown();
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port " + this.serverPort, e);
}
}在这一点上,this.threadPool.execute(new ThreadHandler(clientSocket));如果线程是空闲的,我会执行请求。否则它会进入线程池的队列。
您甚至可以将其从固定线程池更改为其他线程池!只需查看执行器并获取所需的内容即可。Executors
希望这能有所帮助!
https://stackoverflow.com/questions/15931405
复制相似问题