2013-05-29 58 views
1

我使用線程和插座爲先,所以我試圖讓聊天(本地)港口問題與Java插座

客戶端A(實際上是服務器):

public class ClientA { 

    public static void main(String[] args) { 

     ServerSocket servsock = null; 
     try { 
      servsock = new ServerSocket(9998); 
      Socket conn = servsock.accept(); 
      System.out.println("server socket listening on local port : " + servsock.getLocalPort()); 
      System.out.println("socket listening on local port : " + conn.getLocalPort()); 
      System.out.println("socket listening on port : " + conn.getPort()); 
      servsock.close(); 

      TReadingSock tls = new TReadingSock(conn); 
      tls.start(); 
      TWritingSock tes = new TWritingSock(conn); 
      tes.start(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

客戶端B ,實際的客戶端:

public class ClientB { 

    public static void main(String[] args) { 

     Socket sock = null; 
     try { 
      sock = new Socket("localhost", 9998); 
      System.out.println("socket listening on local port : " + sock.getLocalPort()); 
      System.out.println("socket listening on port : " + sock.getPort()); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     TReadingSock tls = new TReadingSock(sock); 
     tls.start(); 
     TWritingSock tes = new TWritingSock(sock); 
     tes.start(); 
    } 
} 

打印顯示此:

客戶A:

server socket listening on local port : 9998 
socket listening on local port : 9998 
socket listening on port : 50875 

客戶B:

socket listening on local port : 50875 
socket listening on port : 9998 

所以,愚蠢的,因爲它的出現,我有嚴重的問題,理解整個插座的事情,我來到這裏的唯一的事情就是我的計劃是在不同的端口上偵聽,我不明白爲什麼。我想這對一些人來說一定是顯而易見的,所以我請求你的幫助來照亮我!

在此先感謝。

編輯:謝謝你的所有答案。事情是,對我來說,你需要一個ServerSocket來監聽端口並接受任何試圖連接的客戶端。當它完成時,它會返回一個Socket對象,我將它傳遞給我的線程以便他們可以完成他們的工作。這是ClientA的。客戶端B只是創建一個Socket,它將嘗試連接到9998端口,這是我用ServerSocket監聽的端口,然後將它傳遞給它的線程。事情是,當我啓動我的客戶端(A然後B),並且我在控制檯A中寫入時,控制檯B上沒有任何事情發生(也許我應該早些指定,對不起)。

我猜想這是由於我的套接字使用的端口。我查了一些教程,即使在閱讀你的迴應後,我也沒有看到有什麼問題,所以要麼我錯過了一些非常明顯的概念,要麼不是連接本身,而是我處理連接的方式。爲以防萬一,我會發表帖子的內容:

public class TWritingSock extends Thread { 
    private Socket sockw; 

    public TWritingSock(Socket sockw){ 
     this.sockw = sockw; 
    } 

    @Override 
    public void run(){ 
     try { 
      while(true){ 
       //Recuperation des saisies clavier 
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

       //Ecriture de la saisie 
       PrintWriter pw= new PrintWriter(sockw.getOutputStream(), true); 

       String typed = br.readLine(); 
       if(typed.equals("fin")){ 
        //sockw.close(); 
        System.out.println("fermé"); 
        break; 
       } 
       pw.write(typed); 
      }   
     } catch (IOException e) { 
      e.printStackTrace(); 
     }finally{ 
      try { 
       sockw.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

而且

public class TReadingSock extends Thread { 
    private Socket sockr; 

    public TReadingSock(Socket sockr){ 
     this.sockr = sockr; 
    } 

    @Override 
    public void run(){ 
     try { 
      while(true){ 
       BufferedReader br = new BufferedReader(new InputStreamReader(sockr.getInputStream())); 
       String typed = br.readLine(); 
       if(typed.equals("fin")){ 
        //sockr.close(); 
        System.out.println("fermé"); 
        break; 
       } 
       System.out.println(typed); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     }finally{ 
      try { 
       sockr.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+1

你會更好地閱讀套接字教程。 – jtahlborn

+0

是的閱讀教程,它並不是那麼糟糕。 – Siddharth

回答

2

(我將使用原油和簡單的圖像談論一個插座,請把它看成我的企圖儘可能簡單地解釋這一點。)

將Socket看作隧道。現在,如果我告訴你我的隧道末端是9998,那麼你可以到達它,但是你的隧道盡頭可以是任何東西,這取決於你自己決定。

ClientA(實際上是Server)說的是「我想聽9997端口」。當ClientA連接「好吧,我們已連接,我在端口9998,你在50875」。

ClientB在說「我要到達您的端口9998,我將使用我的端口50875來這樣做。」

這兩個應用程序現在都可以通過隧道進行通信,因爲他們知道它在哪裏。

+0

我選擇了這個作爲我的回答,儘管所有的都是明確而有用的解釋。原來我有點偏執,套接字工作正常,我的問題來自我用來在我的流上操作的對象。 – user2380462

0

好吧,讓我試着簡化你理解的概念。所以,當你閱讀教程時,這將是有意義的。

套接字非常簡單,是客戶端和服務器之間的隧道。當一個人讀,另一個寫道。換句話說,當一個人等待閱讀,另一個人寫入隧道。當讀取成功時,數據可以由接收器處理。

這裏客戶端和服務器都可以進行雙向通信。有些人創建了曲折的模式,服務器等待讀取,客戶端發送數據並進入讀取等待,服務器處理它並回應客戶端。客戶端顯示成功/錯誤。等等等等。

在它們可以進行讀寫操作之前,它們形成一個連接。爲了形成連接,他們需要告訴對方他們的身份(IP地址/ DNS)是什麼。

明白了這一點嗎?

讓我知道你是否需要我解釋端口。

1

Internet上的每個TCP連接由兩對或四個元素組成:端點A IP地址,端點A端口號和端點B IP地址,端點B端口。在運輸級別,地址在IP packet header中指定,而端口在TCP header中指出。這可以明確識別主機和進程(通過端口)傳遞數據包。

當您bind()您正在監聽的「服務器」套接字修復了端點端口號(在您的情況下爲9998)。當客戶端連接到達時,其他三個部分也是固定的 - 您的本地IP是連接到達的網絡接口,遠程IP和端口是連接客戶端,端口通常由操作系統從你的例子中的ephemeral ports,50875池。