.NET

2008-09-26 5 views
44

में अगला टीसीपी पोर्ट खोजें, मैं एक नया नेट.tcp: // localhost: x/सेवा समापन बिंदु WCF सेवा कॉल के लिए एक गतिशील रूप से असाइन किए गए नए खुले टीसीपी पोर्ट के साथ बनाना चाहता हूं।.NET

मुझे पता है कि जब मैं किसी दिए गए सर्वर से कनेक्शन खोलता हूं तो टीसीपी क्लाइंट एक नया क्लाइंट साइड पोर्ट असाइन करेगा।

क्या नेट में अगले खुले टीसीपी पोर्ट को खोजने का कोई आसान तरीका है?

मुझे वास्तविक संख्या की आवश्यकता है, ताकि मैं उपरोक्त स्ट्रिंग का निर्माण कर सकूं, 0 काम नहीं करता है, क्योंकि मुझे उस स्ट्रिंग को दूसरी प्रक्रिया में पास करने की आवश्यकता है, ताकि मैं उस नए चैनल पर वापस कॉल कर सकूं।

+1

http://stackoverflow.com/प्रश्न/35633 9 3/कैसे-कर-i-get-the-port-that-a-wcf-service-is-hear- – keza

उत्तर

91

यहाँ मैं के लिए क्या देख रहा था है:

static int FreeTcpPort() 
{ 
    TcpListener l = new TcpListener(IPAddress.Loopback, 0); 
    l.Start(); 
    int port = ((IPEndPoint)l.LocalEndpoint).Port; 
    l.Stop(); 
    return port; 
} 
+8

और क्या होता है यदि कोई अन्य प्रक्रिया उस पोर्ट को फिर से खोलने से पहले खुलती है ...? –

+5

फिर आपको निश्चित रूप से एक त्रुटि मिलेगी, लेकिन यह मेरे संदर्भ के लिए कोई मुद्दा नहीं था। – TheSeeker

+8

मैंने एक मुफ्त बंदरगाह प्राप्त करने के लिए सफलतापूर्वक इस तकनीक का उपयोग किया। मैं भी दौड़-परिस्थितियों के बारे में चिंतित था, कुछ अन्य प्रक्रियाओं में हाल ही में पता चला-मुक्त-मुक्त बंदरगाह में घुसपैठ कर रहा था। इसलिए मैंने 'var port = FreeTcpPort()' के बीच एक मजबूर 'नींद (100) 'के साथ एक परीक्षण लिखा और मुफ्त बंदरगाह पर एक HttpListener शुरू किया। मैं फिर एक लूप में इस पर 8 समान प्रक्रियाओं को धक्का दे रहा था। मैं दौड़ की स्थिति कभी नहीं मारा सकता था। मेरा अचूक सबूत (विन 7) यह है कि ओएस स्पष्ट रूप से फिर से आने से पहले तात्कालिक बंदरगाहों (कुछ हज़ार) की सीमा के माध्यम से साइकिल चलाता है। तो उपरोक्त स्निपेट बस ठीक होना चाहिए। –

14

0. पोर्ट नंबर का उपयोग करें। टीसीपी स्टैक अगले मुक्त आवंटित करेगा।

+3

पर यह काम नहीं करता है, क्योंकि मुझे उस वास्तविक # की आवश्यकता है, केवल 0 नहीं। मुझे इसकी आवश्यकता है एक स्ट्रिंग बनाने के लिए संख्या। – TheSeeker

+0

इसने मेरी मदद की है। यह वास्तव में काम करता है, अगर आप दूसरी तरफ सूचित करते हैं कि आप जिस पोर्ट को सुन रहे हैं वह है। – user35443

+0

सर्विसहोस्ट होस्ट = नया सर्विसहोस्ट (टाइपऑफ (माईस सर्विस), नया उरी ("net.tcp: // localhost: 0/service")); काम नहीं करेगा? – jcmcbeth

8

पहले बंदरगाह खोलें, फिर दूसरी प्रक्रिया में सही पोर्ट नंबर दें।

अन्यथा यह अभी भी संभव है कि कुछ अन्य प्रक्रिया पहले बंदरगाह खोलती है और आपके पास अभी भी एक अलग है।

+1

क्या आपके पास ऐसा टीसीपी पोर्ट जितना संभव हो सके उतना आसान पाने के लिए कोड नमूना है? – TheSeeker

+0

यह करने का यह तरीका है। सावधान रहना चाहिए, एक दौड़ की स्थिति हो सकती है यदि एक से अधिक प्रक्रिया एक ही बंदरगाह खोलती है। –

1

आप स्थानीय बंदरगाह/समाप्ति बिंदु के रूप में उपयोग करने के लिए एक विशिष्ट श्रेणी inorder में एक मुक्त बंदरगाह प्राप्त करना चाहते हैं:

private int GetFreePortInRange(int PortStartIndex, int PortEndIndex) 
    { 
     DevUtils.LogDebugMessage(string.Format("GetFreePortInRange, PortStartIndex: {0} PortEndIndex: {1}", PortStartIndex, PortEndIndex)); 
     try 
     { 
      IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); 

      IPEndPoint[] tcpEndPoints = ipGlobalProperties.GetActiveTcpListeners(); 
      List<int> usedServerTCpPorts = tcpEndPoints.Select(p => p.Port).ToList<int>(); 

      IPEndPoint[] udpEndPoints = ipGlobalProperties.GetActiveUdpListeners(); 
      List<int> usedServerUdpPorts = udpEndPoints.Select(p => p.Port).ToList<int>(); 

      TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections(); 
      List<int> usedPorts = tcpConnInfoArray.Where(p=> p.State != TcpState.Closed).Select(p => p.LocalEndPoint.Port).ToList<int>(); 

      usedPorts.AddRange(usedServerTCpPorts.ToArray()); 
      usedPorts.AddRange(usedServerUdpPorts.ToArray()); 

      int unusedPort = 0; 

      for (int port = PortStartIndex; port < PortEndIndex; port++) 
      { 
       if (!usedPorts.Contains(port)) 
       { 
        unusedPort = port; 
        break; 
       } 
      } 
      DevUtils.LogDebugMessage(string.Format("Local unused Port:{0}", unusedPort.ToString())); 

      if (unusedPort == 0) 
      { 
       DevUtils.LogErrorMessage("Out of ports"); 
       throw new ApplicationException("GetFreePortInRange, Out of ports"); 
      } 

      return unusedPort; 
     } 
     catch (Exception ex) 
     { 

      string errorMessage = ex.Message; 
      DevUtils.LogErrorMessage(errorMessage); 
      throw; 
     } 
    } 



private int GetLocalFreePort() 
    { 
     int hemoStartLocalPort = int.Parse(DBConfig.GetField("Site.Config.hemoStartLocalPort")); 
     int hemoEndLocalPort = int.Parse(DBConfig.GetField("Site.Config.hemoEndLocalPort")); 
     int localPort = GetFreePortInRange(hemoStartLocalPort, hemoEndLocalPort); 
     DevUtils.LogDebugMessage(string.Format("Local Free Port:{0}", localPort.ToString())); 
     return localPort; 
    } 





public void Connect(string host, int port) 
    { 
     try 
     { 
      //Create socket 
      Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      //socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

      var localPort = GetLocalFreePort(); 
      //Create an endpoint for the specified IP on any port 
      IPEndPoint bindEndPoint = new IPEndPoint(IPAddress.Any, localPort); 

      //Bind the socket to the endpoint 
      socket.Bind(bindEndPoint); 

      //Connect to host 
      socket.Connect(IPAddress.Parse(host), port);     

      socket.Dispose(); 
     } 
     catch (SocketException ex) 
     { 
      //Get the error message 
      string errorMessage = ex.Message; 
      DevUtils.LogErrorMessage(errorMessage); 
     } 
    } 


    public void Connect2(string host, int port) 
    { 
     try 
     { 
      //Create socket 

      var localPort = GetLocalFreePort(); 
      //Create an endpoint for the specified IP on any port 
      IPEndPoint bindEndPoint = new IPEndPoint(IPAddress.Any, localPort); 

      var client = new TcpClient(bindEndPoint); 
      //client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //will release port when done 

      //Connect to host 
      client.Connect(IPAddress.Parse(host), port);     

      client.Close();    
     } 
     catch (SocketException ex) 
     { 
      //Get the error message 
      string errorMessage = ex.Message; 
      DevUtils.LogErrorMessage(errorMessage); 
     } 
    } 
2

हैं आप बस एक शुरुआती बंदरगाह देना चाहते हैं, और इसे अगले टीसीपी बंदरगाह पर उपलब्ध कराने दें, इस तरह के कोड का उपयोग करें:

public static int GetAvailablePort(int startingPort) 
{ 
    var portArray = new List<int>(); 

    var properties = IPGlobalProperties.GetIPGlobalProperties(); 

    // Ignore active connections 
    var connections = properties.GetActiveTcpConnections(); 
    portArray.AddRange(from n in connections 
         where n.LocalEndPoint.Port >= startingPort 
         select n.LocalEndPoint.Port); 

    // Ignore active tcp listners 
    var endPoints = properties.GetActiveTcpListeners(); 
    portArray.AddRange(from n in endPoints 
         where n.Port >= startingPort 
         select n.Port); 

    // Ignore active udp listeners 
    endPoints = properties.GetActiveUdpListeners(); 
    portArray.AddRange(from n in endPoints 
         where n.Port >= startingPort 
         select n.Port); 

    portArray.Sort(); 

    for (var i = startingPort; i < UInt16.MaxValue; i++) 
     if (!portArray.Contains(i)) 
      return i; 

    return 0; 
} 
+0

पूरी तरह से काम करें! – Bestter

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