2016-10-05 112 views
2

以下是接受客户端套接字连接并为每个连接分配线程的代码(JAVA)。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 

假设一个客户端发送消息“杀 - 客户端1”,我希望最终客户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(); 
} 
} 

我怎样才能做到这一点?

+0

所以你basicly想为客户能够杀死其他客户端:) – Antoniossss

+0

@Antoniossss是的,先生。 –

回答

1

只需跟踪所有客户端套接字和/或处理线程。

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()

如果您跟踪线程,您可以设置“中断”标志并在while条件中进行探测,以便您的处理线程能够优雅地完成工作。

+0

似乎这让我更接近,让我试试谢谢!如果这有效,我会接受答案。 –

+0

我决定使用你的答案逻辑和@Nicolas Filottoanswer的组合。谢谢 ! –

0

要停止当前线程,你close the socket,并从运行返回()方法:

if (clientCommand.equalsIgnoreCase("Kill")) { 
    clientSocket.close(); 
    return; 
} 

编辑:

关闭另一个线程,你可以,例如

  • 在线程之间共享clientID-Thread条目的线程安全映射。当一个新的客户端连接时,你在这张地图上存储为这个客户端启动的线程
  • 当一个Kill-client1命令进来时,你得到线程从地图上相应的“client1”键,并且在这个地方调用nterrupt()线。
  • 在每个线程(例如,client1线程)中,在循环的每次迭代中,检查Thread.currentThread()。isInterrupted()的值。如果是,则关闭连接,从共享映射中删除线程,然后从run()方法中返回。

关键是你永远不会杀死另一个线程。您总是通过中断来请求线程停止,并且线程检查中断标志的值以决定何时以及如何停止。

+0

我不想让线程自己杀死,而是我想要其他线程或者父进程根据线程ID来杀死它。 –

+0

然后你应该澄清你的问题,因为那还不清楚。线程如何根据命令“Kill”知道要杀死哪个线程? –

+0

是的你是对的让我编辑我的问题,但请帮助 –

0

就终止循环:

while (running) { 
    String clientCommand = in .readLine(); 

    if (clientCommand.equalsIgnoreCase("Kill")) { 
     running = false; 
    } 
    } 

或:

while (running) { 
    String clientCommand = in .readLine(); 

    if (clientCommand.equalsIgnoreCase("Kill")) { 
     break; 
    } 
    } 

而且不要忘记关闭插座finally块。

+0

我不希望线程自己杀死,而是我想要其他线程或可能父进程杀死它基于线程ID –

1

你可以做到这一点通过使用线程ID为重点

// 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(); 

然后当一个kill启动存储您Threads线程安全的地图(因为它会由多个线程同时访问)

String clientCommand = in.readLine().toLowerCase(); 
if (clientCommand.startsWith("kill")) { 
    main.interrupt(Long.valueOf(clientCommand.substring(4).trim())); 
} 

然后在主类的方法将是这样的:

public void interrupt(long threadId) { 
    // Remove the thread from the map 
    ClientServiceThread cliThread = threads.remove(threadId); 
    if (cliThread != null) { 
     // Interrupt the thread 
     cliThread.interrupt(); 
    } 
} 

最后,你将需要ClientServiceThread类敏感中断

try { 
    ... 
    while (!Thread.currentThread().isInterrupted()) { 
     // My code here 
    } 
} finally { 
    clientSocket.close(); 
} 
+0

我决定使用你的答案逻辑和@Antoniossss答案的组合。谢谢 ! –