Pregunta

Quiero crear un nuevo net.tcp: // localhost: x / Endpoint de servicio para una llamada de servicio WCF, con un nuevo puerto TCP abierto asignado dinámicamente.

Sé que TcpClient asignará un nuevo puerto del lado del cliente cuando abro una conexión a un servidor determinado.

¿Hay una forma sencilla de encontrar el siguiente puerto TCP abierto en .NET?

Necesito el número real, para poder construir la cadena de arriba. 0 no funciona, ya que necesito pasar esa cadena a otro proceso, para poder volver a llamar a ese nuevo canal.

¿Fue útil?

Solución

Aquí está lo que estaba buscando:

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

Otros consejos

Use un número de puerto de 0. La pila TCP asignará el siguiente libre.

Primero abra el puerto, luego dé el número de puerto correcto al otro proceso.

De lo contrario, todavía es posible que algún otro proceso abra el puerto primero y aún tengas otro diferente.

Es una solución comparable a la respuesta aceptada de TheSeeker. Aunque creo que es más legible:

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

Si solo quieres dar un puerto de inicio y dejar que te devuelva el siguiente puerto TCP disponible, usa un código como este:

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

Si desea obtener un puerto libre en un rango específico para usarlo como puerto / punto final local:

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);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top