2010-05-12 44 views
15

我是新來的Java編程的Socket編程,並試圖瞭解下面的代碼是不是一個錯誤的事情。我的問題是:Java套接字:同一機器上同一端口上的多個客戶端線程?

我可以讓每個線程試圖連接到服務器實例在同一程序,預計在服務器上的多個客戶端來閱讀和與客戶」

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)); 
    } 
} 

之間的隔離寫入數據現在可以我有不同的線程試圖將當前計算機的同一個端口上連接多個客戶的實例?

例如,

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

回答

3

只要您只有一個對象試圖綁定端口進行偵聽,那麼連接多個客戶端就沒有問題。

+0

謝謝你們的東西,我以爲端口作爲一個單一的物理實體(如線),因爲它有一個單一的數字。所以我的想法是它只能被一個客戶端套接字使用,否則多個客戶端套接字一次可以寫入同一個線路。但是從你的答案來看,我認爲端口本身是由多個資源組成的(比如內存塊),但是套接字將被綁定到可能由某個綁定鍵索引的那些塊之一。 – espcorrupt 2010-05-13 04:16:34

+3

該端口只是一個數字。它不符合任何物理。 A *連接*由元組{協議,源地址,源端口,目標地址,目標端口}定義。客戶端操作系統將負責確保每個傳出連接的不同出站端口號。因此,即使它們全部來自同一個客戶端源主機,也不會有多次入站連接到同一個目標主機/端口的問題。 – EJP 2010-05-13 10:16:28

0

是的,無論您的客戶是本地還是遠程都無所謂。在你的例子中,重要的是ClientWorker是線程安全的,因爲你的服務器將有多個這個類的實例(每個客戶端連接一個)。

1

在本例中,您的Server一次接受並處理一個客戶端連接。您可以嘗試連接儘可能多的Client,但一次只能處理一個。

您的執行程序邏輯是否爲多線程並不明顯,因爲您沒有提供實現。如果執行者委託一個線程池或類似的東西,你需要確保你的線程安全,因爲你將有多個並行執行的實例。

我當然假設你的Client也是線程安全的,因爲你的問題只涉及Server

8

是的,但是隻有一個客戶端能夠按照寫入的方式連接每個線程。

你可以把你的服務器run()放在while循環中讓多個客戶端連接。 取決於執行者,他們將以串行或並行方式執行。

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

所以。開始:

您可以接受更多的客戶端與一個serversocket,因爲您只接受run-方法中的一個。你只需要再次致電accept()

然後,你在你的for循環中:首先你必須創建一個新的Client對象。那麼你可以撥打c[i].start();而不是c.start()

現在我可以有不同的線程試圖 到 當前機器的同一個端口上連接多個客戶端 實例?

是的,你可以。只需創建新的主題並運行它們。這應該完美。

希望服務器與客戶

您可以使用您的基本IO技術,經驗就像文件IO之間的隔離讀寫 數據:

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!"); 

而對於閱讀使用BufferedReader。

0

您可以嘗試在這些線路上

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); 
    } 
} 
相關問題