Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle multiple requests with select

currently I am working on a chat server/client project. I am struggling with handling multiple requests with select, my server script uses the select module but the client script doesn't. The result is that when ever a user enters message the other clients have to write their own message to read through the conversation. I have searched a lot in the web for examples, but could only find code snippets with sys.stdin which isn't what I want.

I would glad to receive any instruction/explanation.

Server code:

import socket
import select

server_socket = socket.socket()
server_socket.bind(("0.0.0.0", 2855))
server_socket.listen(1)

open_client_sockets = [] # current clients handler
messages_to_send = [] # future message send handler

def send_waiting_messages(wlist):
    for message in messages_to_send:
        (client_socket, data) = message
        if client_socket in wlist: # if current socket in iteration has reading abilities
            client_socket.send(data)
            messages_to_send.remove(message) # remove from future send handler

def broadcast_message(sock, message):
    for socket in open_client_sockets:
        if socket != server_socket and socket != sock:
            socket.send(message)

while True:
    rlist, wlist, xlist = select.select([server_socket] + open_client_sockets, open_client_sockets, []) # apending reading n writing socket to list

    for current_socket in rlist: # sockets that can be read
        if current_socket is server_socket: # if there is a new client
            (new_socket, address) = server_socket.accept() 
            open_client_sockets.append(new_socket) # clients list
        else:
            data = current_socket.recv(1024)
            if len(data) == 0:
                open_client_sockets.remove(current_socket) # remove user if he quit.
                print "Connection with client closed."
                send_waiting_messages(wlist) # send message to specfic client
            else:
                broadcast_message(current_socket, "\r" + '<' + data + '> ')

    # send_waiting_messages(wlist) # send message to specfic client

server_socket.close()

Client code:

import socket
import msvcrt

client_socket = socket.socket()
client_socket.connect(("127.0.0.1", 2855))

data = ""
def read_message():
    msg = ""
    while True:
        if msvcrt.kbhit():
            key = msvcrt.getch()
            if key == '\r': # Enter key
                break
            else:
                msg = msg + "" + key

    return msg

while data != "quit":
    data = read_message()
    client_socket.send(data)
    data = client_socket.recv(1024)
    print data
client_socket.close()
like image 308
Or Amranov Avatar asked Apr 14 '26 08:04

Or Amranov


1 Answers

my server script uses the select module but the client script doesn't.

A solution is to use select also in the client. On Windows unfortunately select does not handle sys.stdin, but we can use the timeout argument to poll the keyboard.

import socket
import select
import msvcrt
client_socket = socket.socket()
client_socket.connect(("localhost", 2855))
msg = ""
while True:
    ready = select.select([client_socket], [], [], .1)
    if client_socket in ready[0]:
        data = client_socket.recv(1024)
        print data, ' '*(len(msg)-len(data))
        print msg,
    if msvcrt.kbhit():
        key = msvcrt.getche()
        if key == '\r': # Enter key
            if msg == "quit":
                break
            client_socket.send(msg)
            msg = ""
            print
        else:
            msg = msg + "" + key
client_socket.close()
like image 51
Armali Avatar answered Apr 15 '26 21:04

Armali



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!