2015-01-26 23 views
5

Bir tcp sunucusu gibi davranmaktan sorumlu bir TcpServer sınıfına sahibim. Aşağıdaki sınıf bulabilirsiniz:İki farklı soket örneği aynı TCP bağlantı noktasını dinleyebilir (Bağlantı noktası zaten kullanılıyor)

public class TcpServer { 
    private ServerSocket serverSocket; 
    private Socket socket; 
    private int locallyBoundPort; 

    public TcpServer() { 


    } 

    public TcpServer(int locallyBoundPort) { 
     try { 
      this.serverSocket = new ServerSocket(locallyBoundPort); 
      serverSocket.setReuseAddress(true); 
     } catch (IOException e) { 
      System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage()); 
     } 
     socket = null; 

    } 

    public void accept() { 
     try { 
      socket = serverSocket.accept(); 
      socket.setReuseAddress(true); 
     } catch (IOException e) { 
      System.out.println("Error at accept : " + locallyBoundPort); 
     } 
    } 



    public void send(Data data) throws IOException { 
     if(socket != null) { 

      ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); 
      out.writeObject(data); 

     } 
    } 

    public Data receive() throws ClassNotFoundException, IOException { 
     if(socket != null) { 

       ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 
       return (Data) in.readObject(); 

     } else { 
      return null; 
     } 
    } 

    public boolean bind(int port) throws IOException { 
     try { 
      this.serverSocket = new ServerSocket(port); 
      this.locallyBoundPort = port; 
     } catch(IOException e) { 
      return false; 
     } 
     return true; 

    } 

    public void close() { 
     try { 
      serverSocket.close(); 
      socket.close(); 
     } catch (IOException e) { 
      OzumUtils.print("IOException in close, TcpServer"); 
     } 

    } 

    public int getLocallyBoundPort() { 
     return locallyBoundPort; 
    } 

    public Socket getSocket() { 
     return socket; 
    } 

    public ServerSocket getServerSocket() { 
     return serverSocket; 
    } 
} 

Ve bunu yapan bir kod parçası var:

Ben kullanım hatası zaten bir port alıyorum Ancak
TcpServer tcpServer = new TcpServer(LocalPort); 
while(1) 
{ 
    tcpServer.accept(); 
    Thread thread = new Thread(new runnable(tcpServer)); 
    thread.start(); 
    tcpServer = new TcpServer(LocalPort); 
} 

. Bağlantının farklı ip veya portu olduğunda, aynı port üzerinden iki bağlantıya izin veren iki farklı soket örneğinin aynı portu dinleyebileceğini düşündüm. Neyi eksik?

+0

Hayır, zaten dinleme durumunda olan bir bağlantı noktasını kullanamazsınız. Bununla birlikte, herhangi bir sayıda müşteri aynı bağlantı noktasına bağlanabilir. – m0skit0

cevap

5

İki tcp sunucu soketini aynı bağlantı noktasına bağlayamazsınız. reuseAddress, gerçekten istemci soketleri içindir ve sizin düşündüğünüz şekilde çalışmaz ... ve kullandığınız şekilde hiçbir şekilde bir şey yapmayacaktır (çünkü bağlandıktan sonra ayarlıyorsunuz).

Aynı bağlantı noktasına iki kez bağlamanız gerekmez. tcpServer = new TcpServer(LocalPort); satırını while döngüsünün altından kaldırmanız yeterlidir.

Bu şekilde çalışmanız, sunucu soketinizi bir kez bağlamanız ve bağlantı noktasını dinlemenizdir. Bir bağlantı geldiğinde, istemciyle iletişim kurmanız için bir istemci soketi ister ve daha fazla bağlantı dinlemeye devam eden özgün sunucu soketi devam eder.

Temel olarak, socket üyesini (ve diğer herhangi bir durumu) TcpServer sayfasından kaldırmanız ve accept yönteminin kabul edilen soketi döndürmesi gerekir. Ardından, runnable ürününüzünyerine bir parametre olarak socket değerini almasını sağlayın ve bunu istemci bağlantısını sunmak için kullanın. Ardından, döngüye accept numaralı telefonu aramaya devam edin ve yeni bağlantıların iş parçacıklarını bildiğiniz şekilde aynı şekilde işleyin.

Veya alternatif olarak, döndürülen istemci soketi ile yeni TcpServer oluşturmak, üzerinde daha sonra, döngü dışında while(true) çağrı accept yuva oluşturur TcpServer gelen sunucu soketi ve bağlantı noktasını kaldırmak ve işlemek için bir iş parçacığı kullanmak bağ.

Onlarla işiniz bittikten sonra istemci soketlerini kapatmayı unutmayın.

+0

Hello. Detaylı yanıtınız için teşekkür ederiz. Netleştirmek için bir şey daha isteyeyim. Bir TCP soketi bir bağlantıyı kabul ettiğinde, diğer konektörleri aynı anda kabul edebilir ve önceki bağlayıcılarla iletişim kurmaya devam edebilir mi? Ohhh, bunu yazarken ServerSocket bir bağlayıcı kabul ettiğinde yeni bir soketin geri verilmesinin sebebi olduğunu anladım. Teşekkür ederim ! –

1

Hayır, zaten dinleme durumunda olan bir bağlantı noktasını kullanamazsınız. Bununla birlikte, herhangi bir sayıda müşteri aynı bağlantı noktasına bağlanabilir. Bağlantı noktasını tekrar dinlemenize gerek yok, sadece mevcut bağlantıyı işlemek ve yeni bir tane beklemek için yeni bir konu açtınız. Örneğin, Runnable uygular ve parametre olarak Socket alan bir sınıf TcpConnectionHanlder var varsayarak, döngü bu özel müşteri (soket) işlemek için TcpConnectionHanlder durumda Sonra

while (true) { //while(1) is not valid Java syntax 
    final Socket tcpSocket = tcpServer.accept(); // Get socket for incoming connection 
    final Thread thread = new Thread(new TcpConnectionHanlder(tcpSocket)); // Create a thread for this socket/client connection 
    thread.start(); // Launch the thread 
    // tcpServer = new TcpServer(LocalPort); <- not needed, port still listening. 
} 

gibi görünecektir.

İlgili konular