Find the next TCP port in .NET

前端 未结 8 687
别跟我提以往
别跟我提以往 2020-11-29 19:40

I want to create a new net.tcp://localhost:x/Service endpoint for a WCF service call, with a dynamically assigned new open TCP port.

I know that TcpClient will assig

相关标签:
8条回答
  • 2020-11-29 20:07

    If you just want to give a starting port, and let it return to you the next TCP port available, use code like this:

    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 讨论(0)
  • 2020-11-29 20:16

    Here is what I was looking for:

    static int FreeTcpPort()
    {
      TcpListener l = new TcpListener(IPAddress.Loopback, 0);
      l.Start();
      int port = ((IPEndPoint)l.LocalEndpoint).Port;
      l.Stop();
      return port;
    }
    
    0 讨论(0)
  • 2020-11-29 20:18

    If you want to get a free port in a specific range in order to use it as local port / end point:

    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 the host
            client.Connect(IPAddress.Parse(host), port);
    
            client.Close();
        }
        catch (SocketException ex)
        {
            // Get the error message
            string errorMessage = ex.Message;
            DevUtils.LogErrorMessage(errorMessage);
        }
    }
    
    0 讨论(0)
  • 2020-11-29 20:23

    First open the port, then give the correct port number to the other process.

    Otherwise it is still possible that some other process opens the port first and you still have a different one.

    0 讨论(0)
  • 2020-11-29 20:24

    Use a port number of 0. The TCP stack will allocate the next free one.

    0 讨论(0)
  • 2020-11-29 20:24

    It's a solution comparable to the accepted answer of TheSeeker. Though I think it's more readable:

    using System;
    using System.Net;
    using System.Net.Sockets;
    
        private static readonly IPEndPoint DefaultLoopbackEndpoint = new IPEndPoint(IPAddress.Loopback, port: 0);
    
        public static int GetAvailablePort()
        {
            using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                socket.Bind(DefaultLoopbackEndpoint);
                return ((IPEndPoint)socket.LocalEndPoint).Port;
            }
        }
    
    0 讨论(0)
提交回复
热议问题