使用select模型与套接字进行python聊天(python chat with sockets using select model)

嘿我正在尝试用python构建一个多用户聊天但是我遇到了select命令的问题。

这是客户:

import socket import select import msvcrt client_socket = socket.socket() client_socket.connect(('127.0.0.1', 23)) messages = [] while True: rlist, wlist, xlist = select.select(client_socket, client_socket, []) for current_socket in rlist: data = current_socket.recv(1024) print data if msvcrt.kbhit(): word = raw_input() client_socket.send(word)

我很确定问题出在这一行 - rlist,wlist,xlist = select.select(client_socket,client_socket,[])

这是服务器:

import socket , select server_socket= socket.socket() server_socket.bind(('0.0.0.0',23)) server_socket.listen(5) open_client_sockets = [] messages_to_send = [] def send_wating_messages(wlist): for message in messages_to_send: (client_socket,data) = message for client_socket in wlist: client_socket.send(data) messages_to_send.remove(message) while True: rlist,wlist,xlist = select.select([server_socket]+open_client_sockets,open_client_sockets,[]) for current_socket in rlist: if current_socket is server_socket: (new_socket,address) = server_socket.accept() open_client_sockets.append(new_socket) else: data = current_socket.recv(1024) if data=="": open_client_sockets.remove(current_socket) print 'Connection with client closed.' else: messages_to_send.append(data) send_wating_messages(wlist)

服务器运行良好,但客户端无法正常工作。

Hey I'm trying to build a multi-user chat with python but I have a problem with the select command.

this is the client :

import socket import select import msvcrt client_socket = socket.socket() client_socket.connect(('127.0.0.1', 23)) messages = [] while True: rlist, wlist, xlist = select.select(client_socket, client_socket, []) for current_socket in rlist: data = current_socket.recv(1024) print data if msvcrt.kbhit(): word = raw_input() client_socket.send(word)

i'm pretty sure that the problem is in this line - rlist, wlist, xlist = select.select(client_socket, client_socket, [])

and this is the server:

import socket , select server_socket= socket.socket() server_socket.bind(('0.0.0.0',23)) server_socket.listen(5) open_client_sockets = [] messages_to_send = [] def send_wating_messages(wlist): for message in messages_to_send: (client_socket,data) = message for client_socket in wlist: client_socket.send(data) messages_to_send.remove(message) while True: rlist,wlist,xlist = select.select([server_socket]+open_client_sockets,open_client_sockets,[]) for current_socket in rlist: if current_socket is server_socket: (new_socket,address) = server_socket.accept() open_client_sockets.append(new_socket) else: data = current_socket.recv(1024) if data=="": open_client_sockets.remove(current_socket) print 'Connection with client closed.' else: messages_to_send.append(data) send_wating_messages(wlist)

the server is well functioning but the client doesn't work.

最满意答案

这不是一个完整的答案,而是一个非阻塞客户端的例子。 我现在无法测试,因为我没有可用的MS Windows,但你会明白这一点

# here and below assume that strings are byte-oriented strings. # In Python 3, where strings are char-oriented, `str.encode()` and `str.decode()` might be in use def msw_nonblocking_raw_input(limit=100): collected = '' for i in range(1, limit): # don't let a user block the program by pressing a key permanently if not msvcrt.kbhit(): break collected += msvcrt.getche() logging.debug('user input [%s]' % collected) return collected def socket_nonblocking_input(sock): try: msg = sock.recv(4096) except socket.error as e: err = e.args[0] if err == errno.EAGAIN or err == errno.EWOULDBLOCK: return '' else: # a "real" error occurred raise # got the message. If it's empty, EOF occured logging.debug('server sent us [%s]' % msg) if not msg: sys.exit(0) # perhaps a more graceful shutdown is required... return msg def socket_nonblocking_output(sock, msg): try: res = sock.send(msg) except socket.error as e: err = e.args[0] if err == errno.EAGAIN or err == errno.EWOULDBLOCK: return msg else: # a "real" error occurred raise # If res is 0, then EOF occured if not res: sys.exit(0) # perhaps a more graceful shutdown is required... logging.debug("we have sent %d bytes out of %d" % (res, len(msg))) return msg[res:] # return the unsent tail of the message # the main cycle data_read = '' data_to_write = '' timeout = 1.000 # 1 second client_socket.setblocking(0) # put the socket into the non-blocking mode while True: sockets_to_write = (client_socket,) if data_to_write else () (to_read, to_write, exceptional) = select((client_socket,), sockets_to_write, (), timeout) if to_read: data_read = socket_nonblocking_input(to_read[0]) # technically sys.stdout could also block (e.g. being piped or simply in a slow terminal) but for the sake of simplicity, don't bother ourselves. if data_read: sys.stdout.write(data_read) if to_write: data_to_write = socket_nonblocking_output(to_write[0], data_to_write) data_to_write += msw_nonblocking_raw_input()

同样,我不确定代码是100%正确,我还没有测试过,即使是语法错误,我现在还没有MS Windows。 但我相信你能理解这个想法。 如果有一些麻烦,请不要犹豫。

Here's not an entire answer but rather an example of a non-blocking client. I can't test it right now because I don't have MS Windows available, but you'll get the idea

# here and below assume that strings are byte-oriented strings. # In Python 3, where strings are char-oriented, `str.encode()` and `str.decode()` might be in use def msw_nonblocking_raw_input(limit=100): collected = '' for i in range(1, limit): # don't let a user block the program by pressing a key permanently if not msvcrt.kbhit(): break collected += msvcrt.getche() logging.debug('user input [%s]' % collected) return collected def socket_nonblocking_input(sock): try: msg = sock.recv(4096) except socket.error as e: err = e.args[0] if err == errno.EAGAIN or err == errno.EWOULDBLOCK: return '' else: # a "real" error occurred raise # got the message. If it's empty, EOF occured logging.debug('server sent us [%s]' % msg) if not msg: sys.exit(0) # perhaps a more graceful shutdown is required... return msg def socket_nonblocking_output(sock, msg): try: res = sock.send(msg) except socket.error as e: err = e.args[0] if err == errno.EAGAIN or err == errno.EWOULDBLOCK: return msg else: # a "real" error occurred raise # If res is 0, then EOF occured if not res: sys.exit(0) # perhaps a more graceful shutdown is required... logging.debug("we have sent %d bytes out of %d" % (res, len(msg))) return msg[res:] # return the unsent tail of the message # the main cycle data_read = '' data_to_write = '' timeout = 1.000 # 1 second client_socket.setblocking(0) # put the socket into the non-blocking mode while True: sockets_to_write = (client_socket,) if data_to_write else () (to_read, to_write, exceptional) = select((client_socket,), sockets_to_write, (), timeout) if to_read: data_read = socket_nonblocking_input(to_read[0]) # technically sys.stdout could also block (e.g. being piped or simply in a slow terminal) but for the sake of simplicity, don't bother ourselves. if data_read: sys.stdout.write(data_read) if to_write: data_to_write = socket_nonblocking_output(to_write[0], data_to_write) data_to_write += msw_nonblocking_raw_input()

Again, I'm not sure that the code is 100% correct, I haven't tested it, even for syntax errors, I don't have MS Windows right now. But I'm sure you can get the idea. If there're some troubles don't hesitate to ask.

更多推荐