2015-09-16 27 views
1

如本文件中所提及:Python socket.accept()Python:同一套接字对象如何服务于不同的客户端?

接受连接。套接字必须绑定到一个地址,并且监听连接。返回值是一对(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

让我重新说一句:你的印象是,如果你听,例如,端口'10000'和客户端连接,每个客户端连接都会获得一个随机的服务器端口来识别连接? – dhke

+0

@dhke是的,我做到了! –

+0

你在混淆套接字和端口。一个服务器端*端口*是所有必需的,但服务器需要每个连接有一个*套接字*。 – EJP

回答

0

我一直认为,服务器将创建一个新的socket对象用不同的随机端口

这需要告诉客户这端口用于连接。很好,这是没有必要的,见下文。

那么服务器如何处理多个客户端呢?

元组(server_addr, server_port, client_addr, client_port)在客户端连接后是唯一的。当数据包进入时,网络堆栈会搜索与此元组相匹配的打开连接,并将传入数据包重定向到相关套接字(/文件描述符)。

服务器套接字(您执行上accept()),是无关(这是listen()荷兰国际集团),但结合。这意味着它没有对方(没有客户端地址),但它有一个本地地址(服务器端)。

accept()返回一个新的套接字。这一个是绑定连接。绑定与上面相同:它具有本地地址和端口。该地址与服务器套接字相同,但客户端套接字状态与服务器套接字的状态不同:已连接。这意味着我们可以与另一方通信的已知对等方(地址)。我们也有同行的地址(对等地址)和套接字。这些信息足以唯一标识连接。

客户端套接字只接受匹配(server_addr, server_port, client_addr, client_port)所有四个数据。

+0

还有一个疑问。服务器如何能够在同一个套接字上监听并为客户端提供服务?无论何时请求到来,操作系统是否总是使用一个未连接但绑定的套接字,该套接字与连接和绑定的套接字不同? –

+0

@KartikAnand注意术语。 * socket *本质上是操作系统为您提供的与网络栈交互的句柄。你不能有一个既监听又连接的套接字。然而,如果一个*连接建立请求*(例如TCP'SYN')包进来与一个已建立的连接相匹配,它将被现有连接处理(因此通常被忽略)。如果您已经拥有一个地址,则无法创建具有相同地址四倍的连接。 – dhke

+0

感谢您的信息。你能否指出我在这些具体细节所涵盖的特定资源上?我无法使用Google找到他们! –

相关问题