如何使服务器监听多个端口

6
我希望使用同一台服务器监听100个不同的TCP端口,以下是我目前的做法:-
import socket
import select

def main():

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    for i in range(1000,1100):
        server_socket.bind(('127.0.0.1', i))
    server_socket.listen(1)

    read_list = [server_socket]
    while True:
        readable, writable, exceptional = select.select(read_list, [], read_list)
        for s in readable:
            if s is server_socket:
                #print "client connected"
                client_socket, address = server_socket.accept()
                read_list.append(client_socket)
            else:
                # One of the tcp clients
                data = s.recv(1024)
                if not result:
                    s.close()
                    read_list.remove(s)
                    #print "client disconnected"

if __name__ == "__main__":
    main()

出现错误信息“权限被拒绝”,可能是因为某些端口(1000-1100)被保留并未分配,或者由于其他原因。

我尝试使用(8000-8100)时,它显示“参数无效”。

编辑过的内容

import socket
import select

def create_socket(TCP_PORT):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('127.0.0.1', TCP_PORT))
    server_socket.listen(1)

    return server_socket


def main():

    read_list = []

    for TCP_PORT in range(8000,8100):
        read_list.append(create_socket(TCP_PORT))

    while True:
        readable, writable, exceptional = select.select(read_list, [], read_list)
        for s in readable:
            if s is server_socket:
                #print "client connected"
                client_socket, address = server_socket.accept()
                read_list.append(client_socket)
            else:
                # One of the tcp clients
                data = s.recv(1024)
                if not result:
                    s.close()
                    read_list.remove(s)
                    #print "client disconnected"

if __name__ == "__main__":
    main()
3个回答

6

有两个问题。

  1. 端口1024以下被保留。 (您需要特殊权限,例如root权限来绑定此类端口)。

  2. 一个套接字只能监听一个端口。因此,要监听多个端口,您需要为每个端口创建一个套接字。


感谢您的快速回复。正如我所想,1000-1100必须被保留,因此权限被拒绝。说到第二点!!!这意味着要在100个不同的端口上进行监听,我需要创建100个不同的套接字对象吗? - Praful Bagai
这意味着我需要手动完成它,一遍又一遍地编写相同的代码行,还是可以使用循环来处理它? - Praful Bagai
当然,您可以使用循环创建套接字并绑定它。将socket()调用的返回值保存在列表中,并将其传递给select()函数。 - nos
会是这样吗?我已经编辑了我的问题,并提供了我目前正在执行的解决方案。它正确吗?请确认。 - Praful Bagai
是的。你还需要更改if s is server_socket,以检查它是否是你的服务器套接字之一 - 这意味着你可能需要两个列表,一个包含你的服务器套接字,另一个包含你传递给select()的所有套接字。 - nos
请提供一个示例。谢谢。 - Praful Bagai

1
在这里,您会找到一份详细的解释: 从一个服务器监听多个端口。它是针对C语言的,但问题在Python中是相同的。
所以答案也是一样的:
  • 每个端口一个套接字
  • 每个套接字一个监听
  • 单个选择器
顺便提一下,Unix(和类Unix)系统下1024以下的端口是保留的:您需要root权限才能使用它们。在Windows上,没有此类限制。

我的C语言知识很少,我无法弄清楚实际发生了什么。你能否提供一段类似的Python代码呢?这将是非常有帮助的。谢谢。 - Praful Bagai

0
关于第二个问题 - 使用8000-8100端口会导致“无效参数”错误,这是因为在重新绑定已经绑定的套接字之前没有先重新创建套接字。但是,该端口范围本身并没有问题。
>>> s=socket.socket()
>>> s.bind(('localhost', 8001))
>>> s.bind(('localhost', 8001))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 22] Invalid argument
>>> s.close()
>>> s.bind(('localhost', 8001))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
  File "/usr/lib64/python2.7/socket.py", line 170, in _dummy
    raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
>>> s=socket.socket()
>>> s.bind(('localhost', 8001))

1
我明白,但是我要如何绑定“多个”端口/接收来自多个端口的数据呢? - Praful Bagai
我会建议:使用多个绑定在不同端口的SocketServer实例(或socketserver),并将它们全部绑定到相同的__handle_callback函数。 - Alexis Paques

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接