Python 客户端套接字正在连接,即使服务器不接受新连接并且积压大小为 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(( 调用仍然没有阻塞或抛出异常。它指出:"客户端:连接成功"。发生了什么事?我预计调用会阻止,因为我从未指定超时,并且永远不会接受连接。

我希望你们中的某个人可以向我详细解释发生的事情。我在Stackoverflow和其他方面找到了类似的主题,但我还没有找到一个答案来摆脱我的困惑。

问候 镜子

编辑:

在对wireshark进行进一步调查后,我发现了以下内容:

  1. server.listen(x( "启动"套接字。从这一点开始,服务器套接字可以通过响应客户端启动三向握手来执行三向握手。

  2. server.listen(x( 允许积压工作 (backlog( 中最多 x 个元素。这意味着最多 x 个元素可以执行三次握手。在执行之后或执行期间,它们将在积压工作中排队。如果服务器套接字调用 .accept((,它们将从积压工作中取出。因此,积压队列始终包含已经执行 3 次握手或当前正在执行的客户端连接。x 确定此积压工作队列的大小。

      似乎server.listen(
    1. 0(与server.listen(1(具有相同的效果。只有一个连接能够执行 3 向握手并包含在积压工作队列中。因此,我的猜测是,python套接字实现是,.listen(...(必须具有至少为1的参数值。我想如果它更低,它会调整为 1。

因此,我想稍微改变一下我的问题。现在很明显为什么socket.connect((不抛出异常或阻塞。它可以成功执行 3 次握手并且连接已打开。但是socket.accept((是做什么的呢?它显然从积压队列中取出了一个元素,但它在服务器和客户端之间的通信以及 tcp 协议方面意味着什么?

但是socket.accept((是做什么的呢?它显然从积压队列中取出了一个元素,但它在服务器和客户端之间的通信以及 tcp 协议方面意味着什么?

它在服务器和客户端之间的通信以及 tcp 协议方面没有任何作用。它只是将进程的文件描述符与连接相关联,即它设置操作系统数据结构。我们可以看到效果netstat,例如在带有-b-o选项的Windows上。

最新更新