套接字服务器没有在 recv() 上暂停。立即读取 0 个字节并关闭
Socket server not pausing on recv(). Immediately reads 0 bytes and closes
我有一个服务器-客户端设置,其工作方式如下:
- 客户端连接到服务器。
- 客户端向服务器发送一条 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 声明如下:
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 的问题。
如果我尝试从客户端发送 "test",它会将大小注册为 4 字节并告诉服务器读取 4 字节。从终端,nc 将改为发送 "test\n"。换行符 '\n' 不会被读取,而是在队列中等待。当调用第二个 recv() 时,它立即读取 '\n' 并将其作为关闭连接的指示。
我有一个服务器-客户端设置,其工作方式如下:
- 客户端连接到服务器。
- 客户端向服务器发送一条 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 声明如下:
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 的问题。
如果我尝试从客户端发送 "test",它会将大小注册为 4 字节并告诉服务器读取 4 字节。从终端,nc 将改为发送 "test\n"。换行符 '\n' 不会被读取,而是在队列中等待。当调用第二个 recv() 时,它立即读取 '\n' 并将其作为关闭连接的指示。