python - 套接字服务器未在 recv() 上暂停。立即读取 0 字节并关闭
问题描述
我有一个服务器客户端设置,其工作方式如下:
- 客户端连接到服务器。
- 客户端向服务器发送一条 64 字节的消息,告诉服务器要读取多少数据
- 服务器读取那么多字节的数据,做出响应,然后重复该过程。
- 当客户端完成后,它会向服务器发送一个空消息
- 服务器看到消息长度为0并关闭连接。
这似乎适用于第一遍。但是,在服务器响应之后,它不会等待客户端发送更多数据。相反,服务器立即读取 64 个字节。由于客户端没有响应,所以消息长度为0,连接关闭。
我不确定为什么在客户端发送更多数据之前服务器不会暂停。
这是服务器循环:
self.__stop = False
while not self.__stop:
if self.client_sock:
# Check if the client is still connected and if data is available
try:
rdy_read, rdy_write, sock_err = select.select(
[self.client_sock, ], [self.client_sock, ], [], 5)
except select.error as err:
self.stop()
return
if len(rdy_read) > 0:
# msg length will be sent as bytes
read_data = self.client_sock.recv(64)
# Check if the socket has been closed
if read_data == 0:
self.stop()
else:
msg_length = int(read_data)
msg = self.client_sock.recv(msg_length)
response = f"{[12, 15, 66]}\n"
msg_size = padded_size_of_msg(response)
self.client_sock.send(msg_size)
self.client_sock.send(f"{response}".encode('utf-8'))
else:
print(
f"[THREAD {self.number}] No client connected.")
self.stop()
self.close()
函数 padded_size_of_msg() 用于计算消息的长度,将该数字填充为 64 字节,然后将其发送给客户端:
def padded_size_of_msg(msg):
msg_length = len(msg)
send_length = str(msg_length).encode('utf-8')
send_length += b' ' * (64- len(send_length))
return send_length
完整的类声明如下:
class ServerSocketThread(Thread):
def __init__(self, client_sock, client_addr, number):
Thread.__init__(self)
self.client_sock = client_sock
self.client_addr = client_addr
self.number = number
def run(self):
self.__stop = False
while not self.__stop:
if self.client_sock:
# Check if the client is still connected and if data is available
try:
rdy_read, rdy_write, sock_err = select.select(
[self.client_sock, ], [self.client_sock, ], [], 5)
except select.error as err:
print(
f"[THREAD {self.number}] Select() failed on socket with {self.client_addr}")
self.stop()
return
if len(rdy_read) > 0:
# msg length will be sent as bytes
read_data = self.client_sock.recv(64)
# Check if the socket has been closed
if read_data == 0:
print(
f"[THREAD {self.number}] {self.client_addr} closed the socket")
self.stop()
else:
msg_length = int(read_data)
# Client will send msg as bytes. No need to decode to str
msg = self.client_sock.recv(msg_length)
response = f"{[12, 15, 66]}\n"
# Send outputs to client as bytes
msg_size = padded_size_of_msg(response)
self.client_sock.send(msg_size)
self.client_sock.send(f"{response}".encode('utf-8'))
else:
print(
f"[THREAD {self.number}] No client connected.")
self.stop()
self.close()
def stop(self):
self.__stop = True
def close(self):
if self.client_sock:
print(
f"[THREAD {self.number}] Closing conn with {self.client_addr}")
self.client_sock.close()
解决方案
这最终成为从命令行使用 nc 的问题。
如果我尝试从客户端发送“测试”,它会将大小注册为 4 字节并告诉服务器读取 4 字节。从终端,nc 将改为发送“test\n”。换行符 '\n' 不会被读取,而是在队列中等待。当调用第二个 recv() 时,它立即读取 '\n' 并将其作为关闭连接的指示。
推荐阅读
- javascript - 使用基于 json 文件的值检查输入值
- java - Gradle 7.0 迁移:如何从 compileClasspath 中删除 JAR
- r - 仅对列表中的数字部分求和
- azure-devops - Synapse - 无法正确部署 SQL 链接服务器
- java - 连接本地主机失败(桌面)
- python-3.x - dagster - 错误 - train_pipeline | S3 URI AWS
- css - 使用纯 CSS 的简单倒计时圆形动画
- python - 项目问题,求图片处理方面的建议
- css - 自定义 div 形状 CSS?
- python - 没有连接到 MariaDB