2015-12-08 16 views
0

我想問爲什麼服務器只顯示第一次客戶端發送數據時,我的意圖是有兩個客戶端,只想發送一些整數,服務器讀取它然後將其發送回另一個客戶端,然後等待該客戶端發送信息並將其發送到另一個客戶端(切換它們)。但是隻有在第一次發送數據時纔會在服務器上讀取數據?服務器Socket數據塊第一次收到數據後

服務器:

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 


public class Server { 

    private ServerSocket serv; 
    private DataInputStream inFromClient1; 
    private DataOutputStream outToClient1; 
    private DataInputStream inFromClient2; 
    private DataOutputStream outToClient2; 

    public Server(){ 
     try { 
      serv=new ServerSocket(8000); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public void listen() throws IOException{ 
     System.out.println("Listening for connections"); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       // TODO Auto-generated method stub 
       while(true){ 
        Socket sock1; 
        Socket sock2; 
        try { 
         sock1 = serv.accept(); 
         sock2=serv.accept(); 
         handleSession(sock1,sock2); 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 

       } 
      } 
     }).start(); 

    } 
    public void handleSession(Socket s1,Socket s2) throws IOException{ 
     DataInputStream in1=new DataInputStream(s1.getInputStream()); 
     DataOutputStream out1=new DataOutputStream(s1.getOutputStream()); 

     DataInputStream in2=new DataInputStream(s1.getInputStream()); 
     DataOutputStream out2=new DataOutputStream(s1.getOutputStream()); 
     while(true){ 

      int inint1=in1.readInt(); 
      System.out.println("Recived from 1 " + inint1); 
      System.out.println("Sending to 2 "); 
      out2.writeInt(in1.readInt()); 
      int inint2=in2.readInt(); 
      System.out.println("Recived from 2 " + inint2); 
      System.out.println("Sending to 1 "); 
      out1.writeInt(inint2); 
     } 
    } 
    public static void main(String[] args) throws IOException { 
     new Server().listen(); 
    } 
} 

Client : 

import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Scanner; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 


public class Client extends JFrame implements ActionListener{ 

    private JPanel mainPanel; 
    private JButton[] buttons; 
    private Socket socket; 
    private int number; 
    private DataInputStream fromServer; 
    private DataOutputStream toServer; 
    private boolean myTurn=true; 

    public Client() throws UnknownHostException, IOException{ 
     mainPanel=new JPanel(new GridLayout(3,3)); 
     socket=new Socket("localhost",8000); 
     add(mainPanel); 
     addbuttons(); 
     setSize(new Dimension(500,400)); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 
    } 

    private void addbuttons(){ 
     buttons=new JButton[9]; 
     for(int i=1;i<10;i++){ 
      buttons[i-1]=new JButton("Rectangle " + i); 
      buttons[i-1].addActionListener(this); 
      mainPanel.add(buttons[i-1]); 
     } 
    } 
    public void actionPerformed(ActionEvent arg0) { 
     JButton butt=(JButton) arg0.getSource(); 
     String str=butt.getText(); 
     String[] splitStr=str.split(" "); 
     number=Integer.parseInt(splitStr[1]); 
     System.out.println(number); 
    } 

    public void start() throws IOException{ 
     fromServer=new DataInputStream(socket.getInputStream()); 
     toServer=new DataOutputStream(socket.getOutputStream()); 

     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       Scanner in=new Scanner(System.in); 
       while(true){ 
        System.out.println("Write some integer"); 
        int inint=in.nextInt(); 
        System.out.println("Before " + myTurn); 
        if(myTurn){ 
         try { 
          toServer.writeInt(inint); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
         myTurn=false; 
        } 
        else{ 
         int fromServint=0; 
         try { 
          fromServint=fromServer.readInt(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
         System.out.println("Recived integer " + fromServint); 
         buttons[fromServint].setText("Some new Text"); 
         myTurn=true; 
        } 
        System.out.println("After " + myTurn); 
       } 
      } 
     }).start(); 
    } 

    public static void main(String[] args) throws UnknownHostException, IOException { 
     new Client().start(); 
    } 
} 

回答

0

您在使用阻擋插座。因此,當你調用任何一種「讀取」方法時,它將阻塞,直到從客戶端接收到數據。

所以,一個線程是不夠的。第一次讀取將被阻止,第二次讀取將永遠不會被執行,除非第一個客戶端實際發送了一些內容。

解決方案1:每個套接字連接使用一個線程(建議,因爲更容易)。 解決方案2:使用非阻塞套接字(不推薦,困難但適用於某些性能嚴重的情況)。

+0

你的意思是,在服務器上,我應該爲每個客戶啓動新的線程? – dobrganch

+0

@dobrgranch,理想情況下,你應該有2個線程,一個監聽,一個分析請求/響應。對於小型項目,每個客戶有一個線程是(可以接受的);但它可能會變成一個嚴重的性能問題與n線程產卵。 – MeetTitan

+0

是的,在服務器上爲每個客戶端連接(=套接字)啓動一個線程,並在客戶端特定線程中執行所有讀/寫處理。 –

1

看起來你正在閱讀從客戶端1 2個整數(猜測它是一個錯字),所以

嘗試更改

out2.writeInt(in1.readInt()); 

out2.writeInt(inint1); 

而且,@JohnBollinger提到,

單獨數據*流是創建,但兩個集都連接到套接字s1,而不是每個套接字設置一個。

DataInputStream in1=new DataInputStream(s1.getInputStream()); 
    DataOutputStream out1=new DataOutputStream(s1.getOutputStream()); 

    DataInputStream in2=new DataInputStream(s1.getInputStream()); 
    DataOutputStream out2=new DataOutputStream(s1.getOutputStream()); 

所有數據流都在這裏引用同一個客戶端。

+0

此外,@ dogbranch,服務器似乎將兩組流連接到同一個客戶端。 –

+0

@JohnBollinger這似乎是客戶/流是不同的,也許你錯了? –

+1

再看一遍。單獨的數據*流被創建,但兩個集都連接到套接字's1',而不是每個套接字都設置一個。 –

0

看看這裏:

int inint1=in1.readInt(); 
System.out.println("Recived from 1 " + inint1); 
System.out.println("Sending to 2 "); 
out2.writeInt(in1.readInt()); 

首先你閱讀從第一個客戶端的int。然後你打印一些東西,並從同一個客戶端讀取第二個int。但客戶端等待來自服務器的int,因此不會發送第二個,所以服務器阻止。 用out2.writeInt(inint1);替換上面代碼的最後一行,看看它是否有效。我沒有閱讀所有的代碼,所以我不確定是否還有其他錯誤。

相關問題