سؤال

أريد الحصول على أي منفذ TCP مفتوح عشوائي على LocalHost في Python. ما هي أسهل طريقة؟

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

المحلول

الحل الحالي:

def get_open_port():
        import socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("",0))
        s.listen(1)
        port = s.getsockname()[1]
        s.close()
        return port

ليس لطيفًا جدًا ولم يكن صحيحًا بنسبة 100 ٪ ولكنه يعمل الآن.

نصائح أخرى

يمكن العثور على المنفذ المجاني عن طريق ربط مقبس إلى منفذ يحدده نظام التشغيل. بعد أن يختار نظام التشغيل منفذًا يمكن التخلص من المقبس. ومع ذلك ، فإن هذا الحل ليس مقاومًا لظروف السباق - في الوقت القصير بين الحصول على رقم المنفذ المجاني واستخدام هذا المنفذ قد يستخدم هذا المنفذ.

def find_free_port():
    s = socket.socket()
    s.bind(('', 0))            # Bind to a free port provided by the host.
    return s.getsockname()[1]  # Return the port number assigned.

أنا في الواقع استخدم ما يلي في أحد برامجي:

port = random.randint(10000,60000)

بالطبع ، هذا أكثر عرضة للتصادمات من الكود الذي لديك. لكنني لم أواجه مشكلة في ذلك. النقطة المهمة هي ، في أي وقت معين ، أن معظم المنافذ المرتفعة غير قيد الاستخدام ، وإذا اخترت واحدة فقط بشكل عشوائي ، فمن غير المرجح أن تكون هناك تعارض مع عملية أخرى أمرًا غير مرجح. إذا قمت بشيء مثل الحل الذي نشرته في إجابتك (فتح مقبس والاستيلاء على رقم المنفذ الخاص به) ، فمن المؤكد تقريبًا أن المنفذ لن يتعارض. لذا ، إذا كان هذا شيئًا ستستخدمه لنفسك فقط (على عكس شيء ستصدره للجمهور) ، فكر فيما إذا كان الأمر يستحق التوصل إلى حل مقاوم للرصاص حقًا. الاحتمالات هي أنها لن تحدث فرقا.

بدافع من تعليق Marcelo Cantos على سؤالك ، سأضيف أن الحل القياسي في مثل هذه الحالات هو أن يكون لديك العملية التي ستستخدم ربط المنفذ بها ثم مشاركة هذه المعلومات مع أي برنامج آخر يحتاج إليها. عادةً ما تفعل شيئًا مثل كتابة ملف مؤقت يحتوي على رقم المنفذ إلى موقع قياسي في نظام الملفات. نظرًا لأن العملية التي تعمل معها لا تفعل ذلك ، فإن أي حل الذي توصلت إليه سيكون بمثابة اختراق. ولكن مرة أخرى ، إذا كان الأمر مجرد استخدامك الخاص ، فمن الجيد على الأرجح.

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

import socket
import errno
import contextlib

reserved_ports = set()

def get_open_port(lowest_port = 0, highest_port = None, bind_address = '', *socket_args, **socket_kwargs):
    if highest_port is None:
        highest_port = lowest_port + 100
    while lowest_port < highest_port:
        if lowest_port not in reserved_ports:
            try:
                with contextlib.closing(socket.socket(*socket_args, **socket_kwargs)) as my_socket:
                    my_socket.bind((bind_address, lowest_port))
                    this_port = my_socket.getsockname()[1]
                    reserved_ports.add(this_port)
                    return this_port
            except socket.error as error:
                if not error.errno == errno.EADDRINUSE:
                    raise
                assert not lowest_port == 0
                reserved_ports.add(lowest_port)
        lowest_port += 1
    raise Exception('Could not find open port')

تقع المنافذ السريعة في النطاق 49152 - 65535. إذا كنت ترغب في التحقق من المنافذ في نطاق أكبر ، فما عليك سوى تغيير القيم في Randint.

import pustil
from random import randint
def getfreeport():
    port = randint(49152,65535)
    portsinuse=[]
    while True:
        conns = pstuil.net_connections()
        for conn in conns:
            portsinuse.append(con.laddr[1])
        if port in portsinuse:
            port = randint(49152,65535)
        else:
            break
    return port
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top