2010-05-12 10 views
15

Ich bin neu in der Socket-Programmierung in Java und versuchte zu verstehen, ob der folgende Code nicht falsch ist. Meine Frage ist:Java-Sockets: Mehrere Client-Threads am gleichen Port auf demselben Rechner?

Kann ich mehrere Clients auf jedem Thread habe versucht, auf eine Server-Instanz im gleichen Programm zu verbinden und erwarten, dass der Server zum Lesen und Schreiben von Daten mit Isolation zwischen Clients“

public class Client extends Thread 
{ 
    ... 
    void run() 
    { 
     Socket socket = new Socket("localhost", 1234); 
     doIO(socket); 
    } 
} 

public class Server extends Thread 
{ 
    ... 
    void run() 
    { 
     // serverSocket on "localhost", 1234 
     Socket clientSock = serverSocket.accept(); 
     executor.execute(new ClientWorker(clientSock)); 
    } 
} 

Jetzt können ich habe mehrere Client-Instanzen auf verschiedenen Threads versuchen, auf dem gleichen Port der aktuellen Maschine?

zum Beispiel zu verbinden,

Server s = new Server("localhost", 1234); 
    s.start(); 
    Client[] c = new Client[10]; 
    for (int i = 0; i < c.length; ++i) 
    { 
     c.start(); 
    } 

Antwort

3

Solange nur ein Objekt versucht, den Port zum Abhören zu binden, ist die Verbindung mehrerer Clients problemlos möglich.

+0

Danke Jungs versuchen können, dachte ich an den Port als eine einzige physische Einheit (wie ein Draht), da es eine einzige Nummer. Also mein Gedanke war, dass es nur von einem Client-Socket genutzt werden kann, sonst könnten mehrere Client-Sockets gleichzeitig in die gleiche Leitung schreiben. Aber von Ihren Antworten denke ich, dass der Port selbst aus mehreren Ressourcen besteht (etwa wie Speicherblöcke), aber der Socket wird an einen dieser Blöcke gebunden, die wahrscheinlich durch einen Binding Key indiziert sind. – espcorrupt

+3

Der Port ist nur eine Nummer. Es entspricht nichts Physischem. Eine * Verbindung * wird durch das Tupel {Protokoll, Quelladresse, Quellport, Zieladresse, Zielport} definiert. Das clientseitige Betriebssystem sorgt dafür, dass für jede ausgehende Verbindung verschiedene ausgehende Portnummern bereitgestellt werden. Es ist also kein Problem, mehrere eingehende Verbindungen zum selben Zielhost/-port zu haben, auch wenn sie alle vom selben Client-Quellhost stammen. – EJP

0

Ja, es spielt keine Rolle, ob Ihre Clients lokal oder remote sind. In Ihrem Beispiel ist es wichtig, dass ClientWorker Thread-sicher ist, da Ihr Server mehrere Instanzen dieser Klasse hat (eine für jede Client-Verbindung).

1

In diesem Beispiel akzeptiert und verarbeitet Ihre Server jeweils eine Clientverbindung. Sie können so viele Client s haben, wie Sie wollen, wenn Sie versuchen, eine Verbindung herzustellen, aber nur eine nach der anderen wird behandelt.

Es ist nicht ersichtlich, ob Ihre Executor-Logik Multithread ist, da Sie die Implementierung nicht bereitgestellt haben. Wenn der Executor an einen Threadpool oder etwas Ähnliches delegiert wird, müssen Sie sicherstellen, dass ClientWorker Thread-sicher ist, da mehrere Instanzen parallel ausgeführt werden.

Ich gehe natürlich davon aus, dass Ihre Client auch threadsicher ist, da Ihre Frage nur die Server betrifft.

8

Ja, jedoch kann nur ein Client pro Thread-Ausführung wie beschrieben eine Verbindung herstellen.

Sie können Ihren Server run() in eine Schleife setzen, während mehrere Clients eine Verbindung herstellen können. Abhängig vom Executor werden sie entweder in Serie oder parallel ausgeführt.

public class Server extends Thread 
    { 
     ... 
     void run() 
     { 
      while(true){ 
       // serverSocket on "localhost", 1234 
       Socket clientSock = serverSocket.accept(); 
       executor.execute(new ClientWorker(clientSock)); 
      } 
     } 
    } 
0

So. Beginnen:

Sie können mehr Clients mit einem Serveranschluss akzeptieren, da Sie nur einen in der run -Methode akzeptieren. Sie müssen nur accept() ein zweites Mal anrufen.

Dann Sie in Ihrer for-Schleife: zuerst müssen Sie jedes Mal ein neues Client Objekt erstellen. Dann können Sie c[i].start(); anrufen und nicht c.start().

Jetzt kann ich mehr Client Instanzen auf verschiedene Threads versuchen auf dem gleichen Port der Strommaschine zu verbinden?

Ja, Sie können. Erstellen Sie einfach neue Threads und führen Sie sie aus. Dies sollte perfekt funktionieren.

erwarten, dass der Server Daten mit Trennung zwischen Kunden

Sie können Ihre Erfahrungen mit grundlegenden IO-Techniken wie mit file-io verwenden, um lesen und schreiben:

OutputStream os = socket.getOutputStream(); 
PrintStream pw = new PrintStream(os, true); // Or PrintWriter, I don't know what the best one is. 
pw.println("Hello, other side of the connection!"); 

Und für Lesen verwendet einen BufferedReader.

0

Sie etwas auf diesen Linien

public class MultiThreadServer extends Application { 
    // Text area for displaying contents 
    private TextArea ta = new TextArea(); 

    // Number a client 
    private int clientNo = 0; 

    @Override // Override the start method in the Application class 
    public void start(Stage primaryStage) { 
    // Create a scene and place it in the stage 
    Scene scene = new Scene(new ScrollPane(ta), 450, 200); 
    primaryStage.setTitle("MultiThreadServer"); // Set the stage title 
    primaryStage.setScene(scene); // Place the scene in the stage 
    primaryStage.show(); // Display the stage 

    new Thread(() -> { 
     try { 
     // Create a server socket 
     ServerSocket serverSocket = new ServerSocket(8000); 
     ta.appendText("MultiThreadServer started at " 
      + new Date() + '\n'); 

     while (true) { 
      // Listen for a new connection request 
      Socket socket = serverSocket.accept(); 

      // Increment clientNo 
      clientNo++; 

      Platform.runLater(() -> { 
      // Display the client number 
      ta.appendText("Starting thread for client " + clientNo + 
       " at " + new Date() + '\n'); 

      // Find the client's host name, and IP address 
      InetAddress inetAddress = socket.getInetAddress(); 
      ta.appendText("Client " + clientNo + "'s host name is " 
       + inetAddress.getHostName() + "\n"); 
      ta.appendText("Client " + clientNo + "'s IP Address is " 
       + inetAddress.getHostAddress() + "\n"); 
      }); 

      // Create and start a new thread for the connection 
      new Thread(new HandleAClient(socket)).start(); 
     } 
     } 
     catch(IOException ex) { 
     System.err.println(ex); 
     } 
    }).start(); 
    } 

    // Define the thread class for handling new connection 
    class HandleAClient implements Runnable { 
    private Socket socket; // A connected socket 

    /** Construct a thread */ 
    public HandleAClient(Socket socket) { 
     this.socket = socket; 
    } 

    /** Run a thread */ 
    public void run() { 
     try { 
     // Create data input and output streams 
     DataInputStream inputFromClient = new DataInputStream(
      socket.getInputStream()); 
     DataOutputStream outputToClient = new DataOutputStream(
      socket.getOutputStream()); 

     // Continuously serve the client 
     while (true) { 
      // Receive radius from the client 
      double radius = inputFromClient.readDouble(); 

      // Compute area 
      double area = radius * radius * Math.PI; 

      // Send area back to the client 
      outputToClient.writeDouble(area); 

      Platform.runLater(() -> { 
      ta.appendText("radius received from client: " + 
       radius + '\n'); 
      ta.appendText("Area found: " + area + '\n'); 
      }); 
     } 
     } 
     catch(IOException e) { 
     ex.printStackTrace(); 
     } 
    } 
    } 

    /** 
    * The main method is only needed for the IDE with limited 
    * JavaFX support. Not needed for running from the command line. 
    */ 
    public static void main(String[] args) { 
    launch(args); 
    } 
} 
Verwandte Themen