如何在套接字编程中选择端口?

7

我目前正在学习Python中的Socket编程,并且对于如何选择服务器要监听的端口感到困惑。我知道我不能选择一些特定的范围(最多3000左右?),所以我选择了远高于该数字的端口(确切地说是7777)。

在我的情况下,我想使用不同数量的服务器来测试我的程序(12的倍数最多达到96个)。到目前为止,我正在使用12个服务器代码测试我的程序,将主机分配给localhost,并将端口号从77777788

有时当我运行程序时,Python解释器会显示:

Traceback (most recent call last):
  File "/home/myUserName/sockettutorial/sockettest4/ppc1/dir12/nwserver12.py", line 9, in <module>
    s.bind((host,port))
  File "<string>", line 1, in bind
socket.error: [Errno 98] Address already in use

尽管我已经杀死了所有可能仍在侦听这些端口的相关进程(使用netstat -plan检查这些进程的PID),但是:
我已经将以下部分包含在我的服务器代码中:
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

我的问题在于尽管出现了错误,程序仍然按预期工作,有时运行程序时根本没有出现这个错误,有时却会出现。不过,这个错误本身有点烦人,如果我想摆脱它,是否有办法让机器/主机为服务器分配可用端口,还是必须手动分配?谢谢大家的回答!

当您列出系统上的所有套接字监听器(例如通过 netstat -a | grep "LISTEN")时,它是否以称为 TIME_WAIT 的模式出现? - HelloWorld
我还没有仔细研究过。我会尝试观察今天并告诉你。 - KhunWasut
1个回答

9
当您绑定服务器以侦听传入连接时,需要指定端口。许多服务都有一个“标准”端口,默认情况下运行在该端口上,例如 HTTP:80、HTTPS:443、SSH:22。这样客户端就知道连接时要将数据发送到哪个端口(如果某个服务运行在随机端口上,则客户端无法连接)。
如果您想让操作系统为您选择一个端口,请绑定到零端口。然后可以使用 getsockname 查找分配给您的端口。示例:
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.bind(('127.0.0.1', 0))
>>> s.getsockname()
('127.0.0.1', 42171)

端口号是一个短整型(16位),因此它们的范围是0-65535。端口号低于1000通常为“已知”服务保留,例如上述提到的服务,并且在其上运行的服务通常需要以ROOT身份运行。

这听起来是个好主意,也许可以编写一个Python脚本以生成针对那些端口的服务器代码,然后同时将客户端代码连接到它们。我会试一试!感谢您的建议。 - KhunWasut
1
端口0用于监听器,让操作系统选择一个未分配的端口并始终工作(除非真的没有可用的端口,这几乎是不可能的)。当监听器绑定到特定端口后,您可以读取操作系统选择的端口号。发现服务可以在本地网络中注册您的服务,以便每个客户端都知道端口号。 - HelloWorld
@HelloWorld 感谢提供的信息。我已经更新了我的答案,建议使用端口0。 - zstewart
1
有一件事我不太明白。假设我将服务器套接字绑定到端口0,那么在客户端编码时应该怎么做呢?也就是说,我如何知道需要连接到特定服务器的哪个端口?(我需要这个信息,因为每个服务器将处理不同的任务,我需要确切地获取来自服务器的数据并保持正确的顺序) - KhunWasut
2
@KhunWasut 如果您要在不同端口上生成一堆服务器,通常会有某种位于已知端口上的主服务器,并且生成的进程将向主服务器报告其IP /端口,并从主服务器获取有关彼此端口号的信息。或者,如果正在生成的服务器数量是固定的,则确实可以为它们选择固定的端口号。如果您想动态生成服务器,则可能需要一个位于固定端口上的主服务器来进行协调。 - zstewart
@zstewart 谢谢您的建议。在我这种情况下应该可行。 - KhunWasut

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