Python 即使服务器不接受新连接且积压大小为 0,客户端套接字仍在连接
Python client socket is connecting even tho server isn't accepting new connection and backlog size is 0
我目前正在 python 中试验套接字。我尝试了以下 3 种变体(跳过代码先阅读问题):
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
time.sleep(3) #Ensure the client socket is created after the server socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
if __name__ == "__main__":
server = Server()
client = Client()
server.start()
client.start()
server.join()
client.join()
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
time.sleep(3) #Ensure server socket is created after client socket
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
#Ensure the server socket is created when the client wants to make a connection
#but the server isn't waiting for new connections when the client establishes a connection
#(.accept() call delayed)
time.sleep(3)
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
time.sleep(1) #Ensure client socket is created after server socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
if __name__ == "__main__":
server = Server()
client = Client()
server.start()
client.start()
server.join()
client.join()
在第一个变体中,可以毫无问题地建立连接。我希望它是这样的,因为服务器正在等待与 .accept() 的新连接。在第二种变体中,由于还没有服务器套接字,因此无法建立连接。连接无法到达目标(发生异常。WinError 1106..something)。也在意料之中。但是第三个让我很困惑。我预计无法建立连接,因为存在服务器套接字,但服务器尚未接受新连接(未调用 .accept())和最大值。积压中的连接数为 0 (.listen(0))。客户端的 .connect() 调用仍然没有阻塞也没有抛出异常。它指出:"CLIENT: Connection sucessful"。发生了什么事?我预计调用会阻塞,因为我从未指定超时并且连接永远不会被接受。
我希望你们中的某个人可以向我详细解释发生了什么。我在 Whosebug 和其他方面发现了类似的主题,但我没有找到消除我困惑的答案。
您好,
Tmirror
编辑:
在使用 wireshark 进一步调查后,我发现了以下内容:
server.listen(x) "fires up" 插座。至此,server socket可以通过响应client发起的三次握手来进行三次握手。
server.listen(x) 允许积压中最多 x 个元素。这意味着最多 x 个元素可以执行三次握手。在执行之后或执行期间,它们在积压中排队。如果服务器套接字调用 .accept(),它们将从积压中取出。因此,积压队列始终包含已经执行 3 次握手或当前正在执行的客户端连接。 x 确定此积压队列的大小。
- 看来[=44=](0)和server.listen(1)的效果是一样的。只有一个连接能够执行 3 次握手并包含在积压队列中。因此我的猜测是,python 套接字实现是,.listen(...) 的参数值必须至少为 1。我想如果它较低,它会被调整为 1。
因此我想稍微改变一下我的问题。现在很明显为什么 socket.connect() 不抛出异常或阻塞。它可以成功执行 3 次握手并且连接打开。但是 socket.accept() 会做什么呢?明明是从backlog队列中取出一个元素,但是对于服务器和客户端之间的通信以及tcp协议来说,这意味着什么?
But what does socket.accept() do then? It obviously takes one element out of the backlog queue, but what does it mean in terms of communication between server and client and in terms of the tcp protocol?
在服务器和客户端之间的通信以及 tcp 协议方面它什么都不做。它只是将进程的文件描述符与连接相关联,即。 e.它建立操作系统数据结构。我们可以看到netstat
的效果,e。 G。在 Windows 上使用 -b
或 -o
选项。
我目前正在 python 中试验套接字。我尝试了以下 3 种变体(跳过代码先阅读问题):
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
time.sleep(3) #Ensure the client socket is created after the server socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
if __name__ == "__main__":
server = Server()
client = Client()
server.start()
client.start()
server.join()
client.join()
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
time.sleep(3) #Ensure server socket is created after client socket
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
class Server(threading.Thread):
def __init__(self):
super(Server, self).__init__()
self.ip = "localhost"
self.port = 23071
self.connectionNumber = 0
def run(self):
self.server= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.ip, self.port))
self.server.listen(self.connectionNumber)
print("SERVER: Server is running")
#Ensure the server socket is created when the client wants to make a connection
#but the server isn't waiting for new connections when the client establishes a connection
#(.accept() call delayed)
time.sleep(3)
print("SERVER: Waiting for connection")
client, addr = self.server.accept()
print("SERVER: Something connected at {}".format(addr))
time.sleep(10) # Simulating doing something
client.close()
self.server.close()
print("Server is closed")
class Client(threading.Thread):
def __init__(self):
super(Client, self).__init__()
self.ip = "localhost"
self.port = 23071
def run(self):
time.sleep(1) #Ensure client socket is created after server socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print("CLIENT. Trying to connect")
self.server.connect((self.ip, self.port))
print("CLIENT. Connection sucessful")
time.sleep(2) # SImulating doing something
except Exception as e:
print("CLIENT: Exception \"{}\" happend".format(e))
finally:
self.server.close()
print("CLIENT: Socket closed")
if __name__ == "__main__":
server = Server()
client = Client()
server.start()
client.start()
server.join()
client.join()
在第一个变体中,可以毫无问题地建立连接。我希望它是这样的,因为服务器正在等待与 .accept() 的新连接。在第二种变体中,由于还没有服务器套接字,因此无法建立连接。连接无法到达目标(发生异常。WinError 1106..something)。也在意料之中。但是第三个让我很困惑。我预计无法建立连接,因为存在服务器套接字,但服务器尚未接受新连接(未调用 .accept())和最大值。积压中的连接数为 0 (.listen(0))。客户端的 .connect() 调用仍然没有阻塞也没有抛出异常。它指出:"CLIENT: Connection sucessful"。发生了什么事?我预计调用会阻塞,因为我从未指定超时并且连接永远不会被接受。
我希望你们中的某个人可以向我详细解释发生了什么。我在 Whosebug 和其他方面发现了类似的主题,但我没有找到消除我困惑的答案。
您好, Tmirror
编辑:
在使用 wireshark 进一步调查后,我发现了以下内容:
server.listen(x) "fires up" 插座。至此,server socket可以通过响应client发起的三次握手来进行三次握手。
server.listen(x) 允许积压中最多 x 个元素。这意味着最多 x 个元素可以执行三次握手。在执行之后或执行期间,它们在积压中排队。如果服务器套接字调用 .accept(),它们将从积压中取出。因此,积压队列始终包含已经执行 3 次握手或当前正在执行的客户端连接。 x 确定此积压队列的大小。
- 看来[=44=](0)和server.listen(1)的效果是一样的。只有一个连接能够执行 3 次握手并包含在积压队列中。因此我的猜测是,python 套接字实现是,.listen(...) 的参数值必须至少为 1。我想如果它较低,它会被调整为 1。
因此我想稍微改变一下我的问题。现在很明显为什么 socket.connect() 不抛出异常或阻塞。它可以成功执行 3 次握手并且连接打开。但是 socket.accept() 会做什么呢?明明是从backlog队列中取出一个元素,但是对于服务器和客户端之间的通信以及tcp协议来说,这意味着什么?
But what does socket.accept() do then? It obviously takes one element out of the backlog queue, but what does it mean in terms of communication between server and client and in terms of the tcp protocol?
在服务器和客户端之间的通信以及 tcp 协议方面它什么都不做。它只是将进程的文件描述符与连接相关联,即。 e.它建立操作系统数据结构。我们可以看到netstat
的效果,e。 G。在 Windows 上使用 -b
或 -o
选项。