簡體   English   中英

使用套接字和選擇模塊的Python2.7聊天(非阻塞代碼)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM