سؤال

أريد إنشاء نقطة نهاية net.tcp://localhost:x/Service جديدة لاستدعاء خدمة WCF، مع منفذ TCP مفتوح جديد تم تعيينه ديناميكيًا.

أعلم أن TcpClient سيقوم بتعيين منفذ جديد من جانب العميل عندما أقوم بفتح اتصال بخادم معين.

هل هناك طريقة بسيطة للعثور على منفذ TCP المفتوح التالي في .NET؟

أحتاج إلى الرقم الفعلي، حتى أتمكن من بناء السلسلة أعلاه.0 لا يعمل، لأنني بحاجة إلى تمرير هذه السلسلة إلى عملية أخرى، حتى أتمكن من معاودة الاتصال بهذه القناة الجديدة.

هل كانت مفيدة؟

المحلول

وهنا ما كنت أبحث عنه:

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

نصائح أخرى

استخدم رقم المنفذ 0.سيقوم مكدس TCP بتخصيص المكدس المجاني التالي.

افتح المنفذ أولاً، ثم قم بإعطاء رقم المنفذ الصحيح للعملية الأخرى.

وإلا فمن الممكن أن تقوم عملية أخرى بفتح المنفذ أولاً ولا يزال لديك منفذ مختلف.

إنه حل مشابه للإجابة المقبولة لـ TheSeeker.على الرغم من أنني أعتقد أنه أكثر قابلية للقراءة:

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

إذا كنت تريد فقط إعطاء منفذ بداية، والسماح له بالعودة إليك بمنفذ TCP التالي المتاح، فاستخدم الكود مثل هذا:

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

إذا كنت ترغب في الحصول على منفذ مجاني في نطاق معين لاستخدامه كمنفذ محلي/نقطة نهاية:

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);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top