嗨,我有一个练习,要使用套接字选择和msvcrt,服务器和mltiplie chat(服务器和客户端需要无阻塞地构建)的客户端进行构建,每个客户端都将发送消息,服务器将消息发送至除了发送邮件的那个服务器以外的所有客户端:
import socket
import select
IP = "192.168.1.154"
port = 123
default_buffer_size = 1024
open_client_sockets = []
messages_to_send = []
def send_waiting_messages(wlist):
for message in messages_to_send:
(client_sock, data) = message
if client_sock in wlist:
for sock in open_client_sockets:
if sock is not client_sock:
sock.send(data)
messages_to_send.remove(message)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((IP, port))
sock.listen(5)
print("The server is on and waiting for client...")
while True:
rlist, wlist, xlist = select.select([sock] + open_client_sockets, open_client_sockets, [])
for current_socket in rlist:
if current_socket is sock:
(new_socket, addr) = sock.accept()
open_client_sockets.append(new_socket)
else:
data = current_socket.recv(default_buffer_size)
if data == "":
open_client_sockets.remove(current_socket)
print("Connection with client closed")
else:
messages_to_send.append((current_socket, 'Hello ' + data))
send_waiting_messages(wlist)
if __name__ == '__main__':
main()
构建服务器并非难事,因为本书对此进行了指导(如果没有进行指导,我将永远无法使这段代码正常工作),但是构建客户端存在问题,主要原因是我不了解{{1} }正常工作,找不到答案可以为我简化此模块。 这是我对客户所做的:
select.select
这可能表明您对模块选择和练习并不了解。我看到一些线程也有类似的问题,但是我对它们一无所知,因此我确实需要很好的移植。 总之,我真的迷路了……
答案 0 :(得分:1)
select
将等待可读性的套接字列表,等待可写性的套接字列表以及等待错误的套接字列表作为参数。它返回准备读,准备写和错误套接字的列表。来自帮助:
>>> help(select.select)
Help on built-in function select in module select:
select(...)
select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
Wait until one or more file descriptors are ready for some kind of I/O.
The first three arguments are sequences of file descriptors to be waited for:
rlist -- wait until ready for reading
wlist -- wait until ready for writing
xlist -- wait for an ``exceptional condition''
If only one kind of condition is required, pass [] for the other lists.
A file descriptor is either a socket or file object, or a small integer
gotten from a fileno() method call on one of those.
The optional 4th argument specifies a timeout in seconds; it may be
a floating point number to specify fractions of seconds. If it is absent
or None, the call will never time out.
The return value is a tuple of three lists corresponding to the first three
arguments; each contains the subset of the corresponding file descriptors
that are ready.
*** IMPORTANT NOTICE ***
On Windows, only sockets are supported; on Unix, all file
descriptors can be used.
因此,要修复客户端,您需要将打开的套接字(sock
)添加到sockets
列表中。如果准备好编写套接字,则可以调用write
函数。
在write
中,使用msvcrt.kbhit()
测试键入的字符。您不能只使用input
,因为它会阻塞。然后,如果已键入字符,则读取该字符。收集字符,直到您按下enter
,然后生成一条消息并将其写入套接字。像这样:
message = []
def write(sock):
if msvcrt.kbhit():
c = msvcrt.getche()
if c == '\r':
data = ''.join(message)
print 'sending:',data
sock.sendall(data)
message.clear()
else:
message.append(c)