[英]Python2.7 chat using sockets and select module(non-blocking code)
嗨,我有一個練習使用套接字選擇和msvcrt,mltiplie聊天的服務器和客戶端(服務器和客戶端需要無阻塞地構建)進行構建,每個客戶端都會發送消息,服務器會將消息發送給所有客戶端除了發送者,服務器:
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()
構建服務器並不難,因為本書指導了服務器的構建(如果沒有指導,我將永遠無法使這段代碼正常工作),但是構建客戶端存在問題,主要原因是我不了解select.select
工作原理,無法找不到可以簡化此模塊的答案。 這是我對客戶所做的:
import socket
import select
import msvcrt
IP = "192.168.1.154"
port = 123
sockets = []
def write():
pass
def main():
sock = socket.socket()
sock.connect((IP, port))
while True:
rlist, wlist, xlist = select.select(sockets, sockets, [])
for current_socket in rlist:
if current_socket is sock:
data = current_socket.recv(1024)
print(data)
else:
sockets.append(current_socket)
write()
if __name__ == '__main__':
main()
這可能表明您對模塊選擇和練習並不了解。 我看到一些線程也有類似的問題,但是我對它們一無所知,因此我確實需要很好的移植。 總之,我真的迷路了...
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.