我尝试在客户端使用非阻塞函数(
select
和mcsvrt
)并对其进行调试,但是当调试器到达select()
行时,它会停止,我不知道我的程序出了什么问题代码。
这是服务器:
import socket
import select
SERVER_IP = '127.0.0.1'
SERVER_PORT = 33333
SERVER_MSG_LENGTH = 6
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((SERVER_IP, SERVER_PORT))
server_socket.listen(5)
open_client_socket = []
msg_to_send = []
def send_waiting_msg(wlist, sender_socket):
for message in msg_to_send:
(client_socket, data) = message
length = str(len(data)).zfill(6)
for client_socket in wlist:
if client_socket != sender_socket:
msg = length + data
client_socket.send(msg.encode())
msg_to_send.remove(message)
def main():
flag = True
print("server is running and listening...")
while flag:
rlist, wlist, xlist = select.select([server_socket] + open_client_socket, open_client_socket, [])
for current_socket in rlist:
if current_socket is server_socket:
client_socket, address = server_socket.accept()
open_client_socket.append(client_socket)
print("connection with {} has been made".format(address))
else:
length = current_socket.recv(SERVER_MSG_LENGTH).decode()
try:
data = current_socket.recv(int(length)).decode()
if data == "quit":
open_client_socket.remove(current_socket)
print("connection has been closed")
else:
print(data)
msg_to_send.append((current_socket, data))
send_waiting_msg(wlist, current_socket)
except Exception as err:
print(err)
exit(-1)
if len(open_client_socket) == 0:
flag = False
server_socket.close()
这是客户:
import socket
import msvcrt
import select
SERVER_HOST = '127.0.0.1'
SERVER_PORT = 33333
SERVER_MSG_LENGTH = 6
client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_sock.connect((SERVER_HOST, SERVER_PORT))
open_client_socket = []
def main():
flag = True
while flag:
ready_to_read, _, _ = select.select([client_sock, msvcrt.getch()], [], [])
for source in ready_to_read:
if source == client_sock:
try:
length = client_sock.recv(SERVER_MSG_LENGTH)
print("send")
data = client_sock.recv(int(length)).decode()
print(data)
except Exception as err:
print(err)
exit(-1)
elif source == msvcrt.getch():
send = msvcrt.getch()
if send == b'quit':
flag = False
length = str(len(send)).zfill(SERVER_MSG_LENGTH)
msg = length + send.decode()
client_sock.send(msg.encode())
client_sock.close()
我尝试在服务器端为我放入
for
中的列表创建一个 select()
循环,它应该使聊天不阻塞。
select()
是一个阻塞函数(当你没有指定超时时)。您要求它等待的条件未得到满足,这就是为什么代码在调用 select()
时停止。
在服务器端,您要求
select()
仅当新客户端连接到服务器或服务器从现有客户端接收数据时解锁。
在客户端,您要求
select()
仅当客户端从服务器接收到数据时才解锁。
我在您的代码中看到的真正问题是msvcrt.getch()
的
误用。你不能用
msvcrt.getch()
来等待 select()
。您正在调用 msvcrt.getch()
(它本身是一个阻塞操作,等待击键可用),然后将返回的字符传递给 select()
,这是错误的。您应该使用 msvcrt.kbhit()
来检测何时调用 msvcrt.getch()
。这意味着您需要从 msvcrt.getch()
中删除 select()
,并为 select()
添加超时,以便您可以定期检查 msvcrt.kbhit()
。或者在单独的线程中实现 msvcrt.getch()
循环。