我有一个工作 Java 服务器(虽然边缘有点粗糙),其中包含 3 个主要类。
第一个类运行服务器并获取套接字以侦听端口并将新连接传递给客户端处理程序。
第二类是线程客户端处理程序
第三个是从客户端处理程序调用并处理信息的协议类。处理完信息后,协议类将经过处理或格式化的响应返回给客户端处理程序以传递给客户端。
优点是第二个类只需要加载可接受的数据即可从套接字接受。数据可以传递给协议处理程序,并且协议处理程序可以加载您希望服务器用来与客户端对话的任何协议。
在这个例子中,我加载了一个基于 telnet 的聊天类。
例如,如果有人离开聊天,客户端处理程序类可能会执行以下代码:
for (i = 0; i < currentClientsConnected; i++) {
if(threads[i] != null && threads[i] != this) {
outputLine = threads[i].serverprotocol.processInput("** " + username + " has left the room **");
threads[i].out.printf(outputLine);
}
}
这将传递"** [username] has left the room **"
给serverprotocol
类,然后以最佳方式返回数据以将消息传输给客户端。在这种情况下,serverprotocol
该类使用 telnet 控制代码格式化消息,告诉客户端重新绘制屏幕,添加新消息并向上滚动缓冲区中现有的当前消息。
例如,我可能只希望客户端处理程序类将消息发送到用户在某些聊天室中的套接字,因此我不想总是发送到所有套接字。
在我的代码中,这是 Class 1 - 接受套接字的服务器类:
while (true) {
int i;
// Try and accept the connection
try {
clientSocket = serverSocket.accept();
// System.out.printf("Remote IP:");
// System.out.printf(clientSocket.getRemoteSocketAddress().toString());
// Find an unused socket if one is available
for (i = 0; i < maxClientsAllowed; i++) {
// If found create thread
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
break;
}
}
// If all sockets are taken
if (i == maxClientsAllowed) {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.printf("Server too busy. Try later.\n");
out.close();
clientSocket.close();
}
} catch(IOException e) {
System.out.println(e);}
}
Class 2 是一个扩展线程的类:
class clientThread extends Thread {
private String clientName = null;
private DataInputStream in;
private PrintWriter out;
private Socket clientSocket = null;
private final clientThread[] threads;
private int currentClientsConnected;
private serverprotocol serverprotocol;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
currentClientsConnected = threads.length;
}
public void run() {
//stuff
}
}
我一直在拼命地尝试查看是否可以使用它来implements Runnable
代替它,但是我没有运气根据线程的实例号调用线程的processInput
(或者应该读取的)方法(在此处的代码中简单地调用) .dataToBeProcessed
i
我见过的最接近的:
它可以利用将服务器作为线程池服务器运行。
但是,sendToAll
在这种情况下,该函数通过 a 直接写入PrintWriter
与套接字关联的 s HashMap
。服务器不允许您发送到单独的协议处理程序类,甚至是单独的ChatServerWorker
类实例。这意味着我不能,例如,仅向套接字 1 和 3 发送消息,然后向套接字 2 发送单独的消息。
我在网上找不到一个可以在不使用extends Thread
.
具体来说,我想保留使用以下行的能力:
threads[i].out.printf(outputLine);
或者
if(threads[i].[class].[var] == 'something') {
// stuff
}
其中整数可用于引用线程实例,或该线程使用的任何类变量或方法。
我错过了什么吗?