2015-01-26 6 views
5

मेरे पास एक टीसीपी सर्वर क्लास है जो अच्छी तरह से एक टीसीपी सर्वर की तरह कार्य करता है। आप नीचे दिए गए वर्ग पा सकते हैं:दो अलग-अलग सॉकेट उदाहरण एक ही टीसीपी पोर्ट (पोर्ट पहले से उपयोग में) सुन सकते हैं

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

और मैं एक कोड टुकड़ा है कि इस करता है:

TcpServer tcpServer = new TcpServer(LocalPort); 
while(1) 
{ 
    tcpServer.accept(); 
    Thread thread = new Thread(new runnable(tcpServer)); 
    thread.start(); 
    tcpServer = new TcpServer(LocalPort); 
} 

हालांकि मैं एक बंदरगाह पहले से ही हो रही है उपयोग में त्रुटि। मैंने सोचा कि दो अलग सॉकेट उदाहरण उसी बंदरगाह को सुन सकते हैं क्योंकि मल्टीप्लेक्सिंग एक ही बंदरगाह के माध्यम से दो कनेक्शन की अनुमति देता है जब कनेक्टर के पास अलग-अलग आईपी या पोर्ट होता है? मुझे क्या याद आ रही है?

+0

नहीं, आप पहले से ही सुनने वाले राज्य में बंदरगाह का उपयोग नहीं कर सकते हैं। हालांकि किसी भी संख्या में ग्राहक इस पोर्ट से जुड़ सकते हैं। – m0skit0

उत्तर

5

आप एक ही बंदरगाह पर दो टीसीपी सर्वर सॉकेट बाध्य नहीं कर सकते हैं। reuseAddress वास्तव में क्लाइंट सॉकेट के लिए है, और यह आपके काम के तरीके से काम नहीं करता है ... और जिस तरह से आप इसका उपयोग कर रहे हैं वह किसी भी तरह से कुछ भी नहीं करेगा (क्योंकि आप बाध्यकारी के बाद इसे सेट कर रहे हैं)।

आपको वास्तव में एक ही बंदरगाह में दो बार बांधने की ज़रूरत नहीं है। अपने while लूप के नीचे से इस लाइन को tcpServer = new TcpServer(LocalPort); हटाएं, और आप सभी सेट हो जाएंगे।

यह काम करने का तरीका यह है कि आप एक बार अपने सर्वर सॉकेट को बांधते हैं और बंदरगाह को सुनते हैं। जब कोई कनेक्शन आता है, तो यह क्लाइंट के साथ संवाद करने के लिए क्लाइंट सॉकेट को फोर्क करता है, और मूल सर्वर सॉकेट अधिक कनेक्शन के लिए सुनना जारी रखता है।

असल में, आपको अपने TcpServer से socket सदस्य (और कोई अन्य राज्य) को हटाने की आवश्यकता है, और accept विधि स्वीकृत सॉकेट को वापस कर दें। फिर runnablesocket को TcpServer के बजाय पैरामीटर के रूप में लें, और क्लाइंट कनेक्शन की सेवा के लिए इसका उपयोग करें। फिर लूप में accept पर कॉल करना जारी रखें, और नए कनेक्शन के लिए थ्रेडिंग थ्रेड को उसी तरह से जानते हैं, सिवाय इसके कि हर बार सर्वर को फिर से न बनाएं।

या, वैकल्पिक रूप से, TcpServer से सर्वर सॉकेट और बंदरगाह निकालने के लिए, उस पर while(true) कॉल accept पाश बाहर सॉकेट बनाने के लिए, तो, एक नया TcpServer लौटे ग्राहक सॉकेट के साथ बनाते हैं, और कार्रवाई करने के लिए एक सूत्र में इसका इस्तेमाल करते हैं कनेक्शन।

क्लाइंट सॉकेट को बंद करने के बाद बंद करना न भूलें।

+0

हैलो। आपकी विस्तृत प्रतिक्रिया के लिए धन्यवाद। मुझे आपको स्पष्ट करने के लिए एक और बात पूछने दो। क्या आप कह रहे हैं कि जब एक टीसीपी सॉकेट कनेक्शन स्वीकार करता है, तो यह एक साथ अन्य कनेक्टर स्वीकार कर सकता है, और पिछले कनेक्टर के साथ संचार कर सकता है? ओह, जब मैं इसे लिख रहा हूं, मुझे एहसास हुआ कि यही कारण है कि सर्वर सॉकेट एक कनेक्टर स्वीकार करते समय एक नई सॉकेट लौटा दी जाती है। धन्यवाद ! –

1

नहीं, आप पहले से ही सुनने वाले राज्य में बंदरगाह का उपयोग नहीं कर सकते हैं। हालांकि किसी भी संख्या में ग्राहक इस पोर्ट से जुड़ सकते हैं। आपको बंदरगाह को फिर से सुनने की आवश्यकता नहीं है, आप वर्तमान कनेक्शन को संसाधित करने के लिए एक नया धागा तैयार करते हैं और एक नया इंतजार करते हैं। उदाहरण के लिए, मान आप एक वर्ग TcpConnectionHanlder कि Runnable लागू करता है और पैरामीटर के रूप में Socket लेता है, पाश की तरह

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. 
} 

तो लगेगा अपने TcpConnectionHanlder उदाहरण में आप इस विशेष ग्राहक (सॉकेट) संभाल।

संबंधित मुद्दे