Python socket/端口问题
我正在写两个小程序,一个是服务器,一个是客户端。每次我同时运行这两个程序,并让客户端连接到服务器时,服务器的输出显示我连接到了一个我在代码中没有绑定的端口。我把服务器和客户端的套接字都绑定到了本地地址和8000端口,但每次客户端连接到服务器时,服务器却说客户端连接在52304端口或者其他大于50000的数字上。难道它不应该是一个固定的端口号吗?即使不是我绑定的那个端口,至少也应该是个常数吧?另外,我知道如果我在同一个终端多次运行服务器程序,即使我退出了程序,那个端口还是会被占用。所以我通常会先运行服务器,退出,然后再关闭终端,这样通常能解决这个问题。还有一点要提的是,当我在同一个终端第二次运行服务器程序时,它会识别出我想绑定到8000端口,但程序不会运行,然后它会选择一个随机的端口。
这是我的服务器代码:
import socket
import os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind('', 8000)
s.listen(5)
while 1:
client,addr = s.accept()
print "Accepted a connection from: ", addr
data = client.recv(1024)
client.send("You said: " + data)
3 个回答
你不能把同一个端口绑定给多个程序,服务器给你的端口就是客户端希望你通过这个端口发送数据的地方。我觉得这样做是为了避免连接冲突。
所以,如果连接已经建立,你就不需要担心端口的问题。
不过,如果你想让服务器能够接收多个连接,可以看看这个链接:多个同时的网络连接 - Telnet 服务器,Python
服务器监听的端口和套接字,并不是在连接建立后用来发送和接收数据的那个套接字。当一个客户端连接时,accept调用会创建一个新的套接字来处理数据的发送和接收。要是用的是同一个套接字,那就会导致其他客户端无法连接进来。
另外,你还需要正确关闭你的套接字,这样在程序结束后,它就不会继续占用资源。
服务器报告的端口号是客户端连接时使用的端口,这个端口号通常是随机的。如果(根据你的问题来看)客户端的 bind
调用和服务器的看起来一模一样,那我很惊讶它能成功,因为服务器已经绑定了那个端口,而一个端口一次只能被一个东西绑定。
请把你的客户端代码发上来。与你的问题暗示的相反,我觉得你并没有在客户端上 bind
到一个端口。我猜你只是在 connect
。一般来说,这就是你应该做的。所以你对结果感到困惑,说明你并不完全理解发生了什么。你看到的结果是完全正常的。
下面是对发生情况的解释:
一个TCP连接是通过以下四个信息唯一标识的(在全球范围内唯一,意思是全世界没有其他TCP连接会有相同的标识,虽然在NAT和私有IP范围内这并不完全正确):
- 客户端IP
- 客户端端口号
- 服务器IP
- 服务器端口号
当你的服务器报告一个连接时,它打印出前两个值,因为这些是通过 accept
调用返回的。当你在服务器上进行 bind
调用时,你是在指定值3和4。操作系统通常会在客户端进行 connect
调用时自动选择值1和2。
客户端通常不会绑定到一个端口(虽然可以这样做)。它通常让操作系统为它选择一个端口。客户端的操作系统会从未使用的端口号列表中选择一个端口号。在你的客户端的 connect
调用中,你提供的是值3和4(服务器端 bind
调用中指定的值)。操作系统应该会自动为你的客户端分配值1和2。
可以把它想象成信封上的发件人和收件人地址。服务器端的 accept
调用报告发件人地址,因为服务器大概已经知道自己的地址。客户端最关心的是收件人地址(服务器的地址),并让一个工作人员(操作系统)来粘贴一个回邮地址。