2016-01-13 146 views
1

我剛開始使用Sockets,對於我當前的項目,我需要能夠從客戶端控制我的程序,但是如果我的項目合作伙伴想同時使用他的客戶端,服務器不會向連接類中顯示的「您已連接」消息發送給他。所以我假設服務器不能同時接受多個客戶端。我曾嘗試使用類Connection的線程,但是也不會將消息「您已連接」發送給第二個客戶端。我在這裏做錯了什麼?在服務器上接受客戶端的多個連接

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

public class Listener extends Thread{ 

private ServerSocket server; 
private int PORT; 
public boolean running; 

public Listener(int port){ 
    try{ 
     this.PORT = port; 
     this.server = new ServerSocket(PORT,10); 
    }catch (IOException e) { 
     System.out.println("Could not create serverSocket..."); 
    } 
} 

@Override 
public void run() { 
    this.running = true; 
    try{ 
     waitForConnection(); 
    }catch(IOException e){ 
     System.out.println("Could not accept connection request.."); 
     run(); 
    } 


} 
public void dispose(){ 
    try{ 
     System.out.println("DISPOSE"); 
     running = false; 
     server.close(); 
    } catch (IOException i) { 
     System.out.println("Could not close ServerSocket"); 
    } 
} 
private void waitForConnection() throws IOException{ 
    while(running){ 
     System.out.println("Waiting for connection"); 
     Socket client = server.accept(); 
     Runnable connection = new Connection(client); 
     new Thread(connection).start(); 
    } 
}  
} 

這是我使用的是有多個用戶同時連接螺紋:

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

public class Connection extends Thread { 
    Socket connection; 
    private ObjectOutputStream output; 
    private ObjectInputStream input; 
    private boolean running; 

    public Connection(Socket connect){ 
      this.connection = connect; 
      try { 
       setupStreams(); 
       whileListening(); 
      } catch (IOException e) { 
       System.out.println("could not connect to: "+ connection.getInetAddress().getHostName()); 
    } 
} 

public void dispose(){ 
    try{ 
     output.close(); 
     input.close(); 
     connection.close(); 
     running = false; 
    }catch(IOException ioException){ 
     ioException.printStackTrace(); 
    } 
} 

private void whileListening(){ 
    String message = "You are connected! "; 
    sendMessage(message); 
    do{ 
     try{ 
      message = (String) input.readObject(); 
      checkMessage(message); 
     }catch(ClassNotFoundException classNotFoundException){ 
      sendMessage("tf did you send? "); 
     }catch (IOException e) { 
      dispose(); 
      run(); 
     } 
    }while(!message.equals("Client - END") && running == true); 
} 

private void setupStreams() throws IOException{ 
    output = new ObjectOutputStream(connection.getOutputStream()); 
    output.flush(); 
    input = new ObjectInputStream(connection.getInputStream()); 
} 

private void sendMessage(String message){ 
    try { 
     output.writeObject("Server - " + message+"\n"); 
     output.flush(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private void checkMessage(String text){ 
     //check the message 
} 
}  

編輯:Addittional信息

之前的第一個客戶端連接,服務器控制檯說: 「等待連接」,然後當第一個客戶端連接時,客戶端控制檯顯示「您已連接」,並且當第二個客戶端連接時,控制檯是黑色的,當我關閉第一個客戶端時,第二個客戶端控制檯顯示「連接「和服務器控制檯說」等待連接「,然後如果關閉第二個客戶端,服務器控制檯會再次顯示」正在等待連接「。

+0

您需要使用非阻塞IO – redFIVE

+0

'System.out.println(「等待連接」);'你是否在朋友嘗試重新連接之前再次看到該文本? – Soulan

+0

@Soulan我在問題中做了一個編輯,我希望能解釋發生了什麼。 – IDutch

回答

2

在你的public class Connection extends Thread你這樣做whileListening()東西構造函數,所以構造函數永遠不會結束,你需要重寫run()功能,做到這一點有

@Override 
public void run() { 
    while(true) { 
     try { 
      whileListening(); 
     } catch(Exception e) {} 
    } 
} 

像這樣,它應該做的伎倆。

+0

非常感謝!我不能相信這是一個小小的錯誤,無論如何它現在工作得很好 – IDutch

0

我認爲你必須先接受,然後你開始線程。

例如,假設這樣的事情

  1. 在主類中,你得到的ServerSocketFactory,然後將ServerSocket。
  2. 然後,(無盡)循環裏面,你等待由的ServerSocket.accept()返回一個新的Socket
  3. 只有在此之後,你開始你的線程

下面是從SSLServerSocket一個例子,這是幾乎相同的邏輯(認爲這是一個僞代碼)

SSLContext sc = SSLContext.getInstance("TLS"); 
    (...) 
    SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
    SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(portNumber); 
    while (listening) { 
     SSLSocket c = (SSLSocket) s.accept(); 
     log.info("Serving"); 
     new SimpleSSLServerSocketThread(c).start(); 
    }