如何处理变长消息并自动关闭套接字?

2024-04-23 21:08:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下情况:

服务器

sock = socket.socket()
sock.bind((hostaddr, port))
sock.listen(backlog)
print(f'Server listenning on {hostaddr}:{port}')

while True:
    client_sock, client_address = self.sock.accept()
    print(f'Incoming connection from {client_address[0]}:{client_address[1]}')

    while True:
        data = client_socket.recv(buffer_size)
        if not data:
           break

        print(f'Received "{data.decode()}" from {client_address[0]}:{client_address[1]}')    

        reply = f'Server: I got the message "{data.decode()}"'.encode()
        client_socket.sendall(reply)

    client_socket.close()

客户

^{pr2}$

我首先启动服务器,然后启动客户端,得到以下日志:

服务器

Server listening on 172.16.0.110:8081
Incoming connection from 172.16.0.110:62388
Received "Lorem Ipsum" from 172.16.0.110:62388

客户

Server reply: I got the message "Lorem Ipsum"

我想得到服务器的回复,然后客户端应该完成,但是服务器和客户端都进入了一个无限循环,永远运行。为什么以及如何解决这个问题?我在IPv4网络中使用Windows10x64上的Python3.6.0。在


Tags: from服务器client客户端dataserveronport
2条回答

您必须定义一个协议,它只是关于如何交换和格式化消息以及如何通信消息边界的规则。看起来您只是希望客户端发送一些数据并读取服务器响应。您可以通过关闭客户端连接的写半部分来实现这一点,在您的例子中,通过在sock.sendall(...)之后调用sock.shutdown(socket.SHUT_WR)。在

在服务器端,这是同一连接的读半部分,服务器将其检测为EOF,导致socket.recv()返回一个长度为零的字节对象。在

对于要在同一连接上发送多个消息的更复杂的协议,必须使用不同的策略。二进制协议的一个简单示例是发送4个字节,表示消息的字节长度,然后将这些字节发送给后续消息本身。在

一种方法是为套接字设置超时,以便在使用socket.settimeout()等待回复时不会永远阻塞,如下所示:

sock = socket.socket()
sock.connect(server_address)
sock.sendall('Lorem Ipsum'.encode())
sock.settimeout(5.0) # sets timeout to 5 seconds

while True:
    data = sock.recv(buffer_size)
    if not data:
        break
    print(data.decode())

sock.close()

相关问题 更多 >