Python 套接字挂在 conn.recv()

Python socket hangs at conn.recv()

我已经使用 python 实现了套接字服务器和客户端。想法是简单地将图像从客户端发送到服务器并从服务器取回文本消息。客户端将从文件系统 select 一个图像文件 (.jpg) 发送到服务器。服务器将接收它并用不同的名称(当前日期时间戳)保存它并发回处理过的文本消息。图像已在服务器端成功发送和保存,但问题是当调用 .recv() 方法从服务器获取消息时客户端挂起。

代码如下

服务器

import socket
import datetime
import time
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1",12345))
server.listen()

print("Server started and listening at port 12345")

BUFFER_SIZE=4096

while True:
    client_socket, address = server.accept();
    # client_socket.setblocking(False)
    print(f"Connection from {address} has been established.")
    file_name = str(datetime.datetime.now()).replace(" ", "").replace(":", "-")
    file_name = file_name + ".jpg"
    
    with open(file_name, "wb") as file:
        recv_data = client_socket.recv(BUFFER_SIZE)
        while (recv_data):
            file.write(recv_data)
            recv_data = client_socket.recv(BUFFER_SIZE)
    
    print("File writing done, preapring data to send...")
    client_socket.send(bytes("Hey there!!!", "utf-8"))
    client_socket.close()

客户

import socket
import threading
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 12345))

BUFFER_SIZE = 4096

with open("client_file.jpg", 'rb') as file:
    file_data = file.read(BUFFER_SIZE)
    while (file_data):
        client.send(file_data)
        file_data = file.read(BUFFER_SIZE)
msg = client.recv(1024) # <-------[[[ hangs here ]]]
print(msg.decode("utf-8"))

存在死锁,因为客户端和服务器都在等待对方发送数据。服务器正在读取输入直到流结束:如果连接仍然打开但客户端没有发送更多数据,服务器中的 client_socket.recv 将挂起。同时客户端正在等待服务器发送一些东西,即 client.recv 挂起。

似乎有一种假设,一旦客户端完成发送,client_socket.recv 将 return 没有数据。不是这种情况。它只会 return 如果客户端已关闭连接或有新数据可用。处理此问题的常用方法是在传输完成时获取一些信息,例如在传输前加上大小前缀或执行 one-sided shutdown.

您需要在发送图片后client.shutdown(socket.SHUT_WR),告诉服务器您已发送完毕。之后它将像 breeze 一样工作