web-dev-qa-db-fra.com

Création d'un serveur de socket qui permet plusieurs connexions via des threads et Java

J'essaie d'adapter mon serveur de socket simple afin qu'il puisse avoir plusieurs connexions TCP, via le multithreading, mais je n'arrive pas à le faire fonctionner. Mon code jusqu'à présent est le suivant, Je ne sais pas vraiment où aller à partir d'ici:

import Java.net.*;
import Java.io.*;

public class DoSomethingWithInput implements Runnable {
   private final Socket clientSocket; //initialize in const'r
   public void run() {


     BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String nextline;
        while ((nextline = in.readLine())!=null) {
           System.out.println(nextline);
        } //... close socket, etc.
    }
}


public class Socket{

  public Socket() {
}
@Override
public void run() {
  try {
    ServerSocket serverSocket = null;
    serverSocket = new ServerSocket(5432);
    for (;;) {
      ServerSocket serverSocket = null;
      serverSocket = new ServerSocket(5432);
      for (;;) {
        Socket clientSocket = null;
        clientSocket = serverSocket.accept();
        //delegate to new thread
        new Thread(new DoSomethingWithInput(clientSocket)).start();
      }
    }
  }catch (IOException e) {
   System.err.println("Could not listen on port: 5432.");
   System.exit(1);
}
}
}

Quelqu'un pourrait-il me donner quelques conseils sur la façon dont je pourrais faire cela, et pourquoi ma mise en œuvre actuelle ne fonctionnera pas? Je parcourais les conseils du Java http://download.Oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServerThread.Java ici , mais l'exemple qu'ils donnent ici semble utiliser beaucoup de sources et de classes externes comme KnockKnockProtocol, etc.

Quelqu'un pourrait-il m'aider avec ça?

Merci beaucoup!

31
michael corrigan

Le problème est qu'actuellement, vous acceptez la connexion, mais effectuez immédiatement des lectures de blocage jusqu'à ce qu'elle soit fermée:

// After a few changes...
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
     clientSocket.getInputStream()));
String nextLine;
while ((nextLine = in.readLine()) != null) {
    System.out.println(nextline);
}

Cela signifie que le même thread qui accepte la connexion essaie de gérer la connexion. Cela ne vous permettra pas d'utiliser plusieurs connexions en même temps.

À la place, créez une classe (par exemple ConnectionHandler) qui implémente Runnable et a un constructeur prenant un Socket. Sa méthode run doit gérer la connexion. Modifiez ensuite votre code en:

Socket clientSocket = serverSocket.accept();
Runnable connectionHandler = new ConnectionHandler(clientSocket);
new Thread(connectionHandler).start();

Cela laissera votre thread "principal" libre d'attendre la prochaine connexion.

(Soit dit en passant, la classe KnockKnockProtocol n'est pas vraiment "externe" - cela fait partie de l'exemple. Ils n'ont tout simplement pas précisé que le la source est ici .. .)

52
Jon Skeet

Vous n'êtes pas multithread. Vous créez un thread qui se lie sur un port, puis lit à partir de n'importe quel socket client jusqu'à ce que la connexion soit fermée.

Vous devez passer le socket à un nouveau thread et le lire.

public class DoSomethingWithInput implements Runnable {
   private final Socket clientSocket; //initialize in const'r
   public void run() {

        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String nextline;
        while ((nextline = in.readLine())!=null) {
           System.out.println(nextline);
        } //... close socket, etc.
    }
}

//...
ServerSocket serverSocket = null;
serverSocket = new ServerSocket(5432);
for (;;) {
    Socket clientSocket = null;
    clientSocket = serverSocket.accept();
    //delegate to new thread
    new Thread(new DoSomethingWithInput(clientSocket)).start();
} //...
20
Mark Peters