JAVA 多线程服务器套接字
JAVA multithreaded server sockets
以下是接受客户端套接字连接并为每个连接分配一个线程的代码(JAVA)。
ServerSocket m_ServerSocket = new ServerSocket();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
假设连接了 5 个客户端,因此有 5 个线程 运行。
client 1: threadId 11
client 2: threadId 12
client 3 :threadId 13
client 4 :threadId 14
client 5 :threadId 15
假设其中一个客户端发送消息 "kill-client1" ,我希望结束客户端 1 的连接并终止 ID 为 11 的线程,如下所示:
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill-client1")) {
// end the connection for client 1 & kill it's corresponding thread 11
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
我怎样才能做到这一点?
要停止当前线程,您 close the socket 和 return 来自 运行() 方法:
if (clientCommand.equalsIgnoreCase("Kill")) {
clientSocket.close();
return;
}
编辑:
要关闭另一个线程,您可以,例如
- 在线程之间共享 clientID-Thread 条目的线程安全映射。当新客户端连接时,您将为此客户端启动的线程存储在此映射中
- 当 Kill-client1 命令进入时,您会从映射中获取与 "client1" 键对应的线程,并在该线程上调用 ìnterrupt()。
- 在每个线程(例如,client1 线程)中,在循环的每次迭代中,您检查 Thread.currentThread().isInterrupted() 的值。如果是,则关闭连接,从共享映射中删除线程,并从
run()
方法中删除 return。
关键是你永远不会杀死另一个线程。您总是通过中断线程来请求它停止,并且线程检查其中断标志的值来决定它必须停止的时间和方式。
只是终止循环:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
running = false;
}
}
或:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
break;
}
}
并且不要忘记关闭 finally
块中的套接字。
只需跟踪所有客户端套接字and/or 处理线程。
Map<Integer,Socket> clients=new HashMap<>();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
clients.put(generateNewClientId(),clientSocket);
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
然后如果你只是做
{
if (clientCommand.equalsIgnoreCase("Kill")) {
Socket socket=clients.get(idToShutDown);// get required id somehow (from request??)
socket.close();
}
}
这将关闭给定的套接字,导致处理线程中断 in.readLine()
,从而完成线程。
如果您跟踪线程,您可以设置 "interrupt" 标志并在 while
条件下探测它,以便您的处理线程能够优雅地完成工作。
您可以通过使用线程 ID 作为键将 Threads
存储到 线程安全映射 中(因为它将被多个线程同时访问)
// Map that will contain all my threads
Map<Long, ClientServiceThread> threads = new ConcurrentHashMap<>();
// Add to the constructor the instance of the class that manage the threads
ClientServiceThread cliThread = new ClientServiceThread(this, clientSocket);
// Add my new thread
threads.put(cliThread.getId(), cliThread);
cliThread.start();
然后当发起杀戮时
String clientCommand = in.readLine().toLowerCase();
if (clientCommand.startsWith("kill")) {
main.interrupt(Long.valueOf(clientCommand.substring(4).trim()));
}
然后在主要 class 你的方法看起来像:
public void interrupt(long threadId) {
// Remove the thread from the map
ClientServiceThread cliThread = threads.remove(threadId);
if (cliThread != null) {
// Interrupt the thread
cliThread.interrupt();
}
}
最后,您需要让您的 class ClientServiceThread
对干扰敏感
try {
...
while (!Thread.currentThread().isInterrupted()) {
// My code here
}
} finally {
clientSocket.close();
}
以下是接受客户端套接字连接并为每个连接分配一个线程的代码(JAVA)。
ServerSocket m_ServerSocket = new ServerSocket();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
假设连接了 5 个客户端,因此有 5 个线程 运行。
client 1: threadId 11
client 2: threadId 12
client 3 :threadId 13
client 4 :threadId 14
client 5 :threadId 15
假设其中一个客户端发送消息 "kill-client1" ,我希望结束客户端 1 的连接并终止 ID 为 11 的线程,如下所示:
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill-client1")) {
// end the connection for client 1 & kill it's corresponding thread 11
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
我怎样才能做到这一点?
要停止当前线程,您 close the socket 和 return 来自 运行() 方法:
if (clientCommand.equalsIgnoreCase("Kill")) {
clientSocket.close();
return;
}
编辑:
要关闭另一个线程,您可以,例如
- 在线程之间共享 clientID-Thread 条目的线程安全映射。当新客户端连接时,您将为此客户端启动的线程存储在此映射中
- 当 Kill-client1 命令进入时,您会从映射中获取与 "client1" 键对应的线程,并在该线程上调用 ìnterrupt()。
- 在每个线程(例如,client1 线程)中,在循环的每次迭代中,您检查 Thread.currentThread().isInterrupted() 的值。如果是,则关闭连接,从共享映射中删除线程,并从
run()
方法中删除 return。
关键是你永远不会杀死另一个线程。您总是通过中断线程来请求它停止,并且线程检查其中断标志的值来决定它必须停止的时间和方式。
只是终止循环:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
running = false;
}
}
或:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
break;
}
}
并且不要忘记关闭 finally
块中的套接字。
只需跟踪所有客户端套接字and/or 处理线程。
Map<Integer,Socket> clients=new HashMap<>();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
clients.put(generateNewClientId(),clientSocket);
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
然后如果你只是做
{
if (clientCommand.equalsIgnoreCase("Kill")) {
Socket socket=clients.get(idToShutDown);// get required id somehow (from request??)
socket.close();
}
}
这将关闭给定的套接字,导致处理线程中断 in.readLine()
,从而完成线程。
如果您跟踪线程,您可以设置 "interrupt" 标志并在 while
条件下探测它,以便您的处理线程能够优雅地完成工作。
您可以通过使用线程 ID 作为键将 Threads
存储到 线程安全映射 中(因为它将被多个线程同时访问)
// Map that will contain all my threads
Map<Long, ClientServiceThread> threads = new ConcurrentHashMap<>();
// Add to the constructor the instance of the class that manage the threads
ClientServiceThread cliThread = new ClientServiceThread(this, clientSocket);
// Add my new thread
threads.put(cliThread.getId(), cliThread);
cliThread.start();
然后当发起杀戮时
String clientCommand = in.readLine().toLowerCase();
if (clientCommand.startsWith("kill")) {
main.interrupt(Long.valueOf(clientCommand.substring(4).trim()));
}
然后在主要 class 你的方法看起来像:
public void interrupt(long threadId) {
// Remove the thread from the map
ClientServiceThread cliThread = threads.remove(threadId);
if (cliThread != null) {
// Interrupt the thread
cliThread.interrupt();
}
}
最后,您需要让您的 class ClientServiceThread
对干扰敏感
try {
...
while (!Thread.currentThread().isInterrupted()) {
// My code here
}
} finally {
clientSocket.close();
}