多客户端聊天服务器选择问题

问题描述 投票:0回答:1

我尝试在客户端使用非阻塞函数(

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()
循环,它应该使聊天不阻塞。

python-3.x sockets
1个回答
0
投票

select()
是一个阻塞函数(当你没有指定超时时)。您要求它等待的条件未得到满足,这就是为什么代码在调用
select()
时停止。

在服务器端,您要求

select()
仅当新客户端连接到服务器或服务器从现有客户端接收数据时解锁。

在客户端,您要求

select()
仅当客户端从服务器接收到数据时才解锁。

我在您的代码中看到的真正问题是msvcrt.getch()

误用
。你不能用
msvcrt.getch()
来等待
select()
。您正在调用
msvcrt.getch()
(它本身是一个阻塞操作,等待击键可用),然后将返回的字符传递给
select()
,这是错误的。您应该使用
msvcrt.kbhit()
来检测何时调用
msvcrt.getch()
。这意味着您需要从
msvcrt.getch()
中删除
select()
,并为
select()
添加超时,以便您可以定期检查
msvcrt.kbhit()
。或者在单独的线程中实现
msvcrt.getch()
循环。

© www.soinside.com 2019 - 2024. All rights reserved.