如文档中所述:Python socket.accept()
接受连接。套接字必须绑定到一个地址和 听取联系。返回值是一对(conn,地址) 其中conn是一个可用于发送和接收数据的新套接字对象 连接,地址是绑定到套接字的地址 连接的另一端。
新创建的套接字是不可继承的。
版本3.4中已更改:套接字现在是不可继承的。
服务器代码是
>>> from socket import *
>>> sock = socket(AF_INET, SOCK_STREAM)
>>> sock.bind(("localhost", 20000))
>>> sock.getsockname()
('127.0.0.1', 20000)
>>> sock.listen(1)
>>> while True:
... conn, address = sock.accept()
... print("Address of client : {0}".format(address))
... print("Address of socket : {0}".format(conn.getsockname()))
...
Address of client : ('127.0.0.1', 47165)
Address of socket : ('127.0.0.1', 20000)
Address of client : ('127.0.0.1', 47166)
Address of socket : ('127.0.0.1', 20000)
客户端代码是
>>> from socket import *
>>> sclient1 = socket(AF_INET, SOCK_STREAM)
>>> sclient2 = socket(AF_INET, SOCK_STREAM)
>>> sclient1.connect(("localhost", 20000))
>>> sclient2.connect(("localhost", 20000))
返回的新socket
对象的地址始终与实际接受连接的原始socket
相同。
我一直认为服务器会创建一个具有不同随机端口的新socket
对象,但是如上所述,即使对于多个客户端,新conn
对象的地址和端口也是如此。还是一样。那么服务器如何处理多个客户端呢?
我知道上面的代码是阻塞的。如果我使用多个线程来处理不同的客户端连接,我将不得不将新的套接字对象和客户端地址发送到我的线程函数。因此,多个线程使用相同的服务器地址和端口处理多个客户端。
线程服务器
>>> from socket import *
>>> import threading
>>> def handler(conn, address):
... print("Address of client : {0}".format(address))
... print("Address of socket : {0}".format(conn.getsockname()))
...
>>> sock = socket(AF_INET, SOCK_STREAM)
>>> sock.bind(("localhost", 20000))
>>> sock.listen(1)
>>> while 1:
... conn, address = sock.accept()
... t = threading.Thread(target=handler, args=[conn, address])
... t.start()
...
Address of client : ('127.0.0.1', 47169)
Address of socket : ('127.0.0.1', 20000)
Address of client : ('127.0.0.1', 47170)
Address of socket : ('127.0.0.1', 20000)
答案 0 :(得分:3)
我一直认为服务器会创建一个具有不同随机端口的新套接字对象
这需要告诉客户端哪个 new 端口用于连接。很好,没有必要,见下文。这也意味着,单个主机地址的开放连接数不能超过65535,这可能会对某些系统造成很大影响。
那么服务器如何处理多个客户端?
元组(server_addr, server_port, client_addr, client_port)
在客户端连接后是唯一的。当数据包进入时,网络堆栈会搜索与此元组匹配的打开连接,并将传入的数据包重定向到相关的套接字(/ file descriptor)。
服务器套接字(您执行accept()
),未连接( listen()
),但绑定。这意味着它在另一端没有对等端(没有客户端地址),但它确实有一个本地地址(服务器端)。
accept()
返回一个新套接字。这个绑定和连接。绑定与上面相同:它有一个本地地址和端口。该地址与服务器套接字相同,但新套接字的状态也是已连接。这意味着我们可以与另一方存在已知的对等方(具有地址)。我们还有对等方的地址(对等地址)和端口(对等端口)。此信息足以唯一标识连接。
客户端套接字仅接受与(server_addr, server_port, client_addr, client_port)
的所有四个匹配的数据。