Home > OS >  I try to make chat room using Python and socket , but i have one problem
I try to make chat room using Python and socket , but i have one problem

Time:04-15

when I send message from client 1 , the message does not appear immediately in client 2 ,Although it appears immediately on the server, on client 2 i should double press "enter" to show other messages.

when I send message from client 1 , the message does not appear immediately in client 2 ,Although it appears immediately on the server, on client 2 i should double press "enter" to show other messages.

the server code :

import socket
import select
import sys
from _thread import *


server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)


if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()

IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.bind((IP_address, Port))
server.listen(5)

list_of_clients = []





def broadcast(message, connection):
    for clients in list_of_clients:
        if clients!=connection:
            try:
                clients.send(message.encode())
            except:
                clients.close()

                remove(clients)

def remove(connection):
    if connection in list_of_clients:
        list_of_clients.remove(connection)

def clientthread(conn, addr):

    # sends a message to the client whose user object is conn
    conn.send(b'chat made by galal')


    while True:
            try:
                message = conn.recv(2048).decode()

                if message:
                    print ("<"   addr[0]   "> "   message)
                    message_to_send = "<"   addr[0]   "> "   message
                    broadcast(message_to_send, conn)
                else:
                    remove(conn)



            except:
                continue


while True:
    conn, addr = server.accept()
    list_of_clients.append(conn)
    print (addr[0]   " connected")
    start_new_thread(clientthread,(conn,addr))  

conn.close()
server.close()

the client code :

import socket
import select
import sys

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))

while True:

    # maintains a list of possible input streams
    sockets_list = [socket.socket(), server]
    read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])

    
    for socks in read_sockets:

        if socks != server:
            message = sys.stdin.readline()
            server.send(message.encode())
            sys.stdout.write("<You>")
            sys.stdout.write(message)
            sys.stdout.flush()
        else:
            message = socks.recv(2048).decode()
            print (message)

server.close()

CodePudding user response:

Your client code waits until pressed enter since there is a sys.stdin.readline() in your client code (Line 17). sys.stdin.readline() waits for the press of your enter key, since it tries to read a newline from your stdin (Your input), therefore blocking the whole execution of your client application.

What you have to do is using separate threads for:

  1. Recieving messages print them
  2. Read from stdin (e.g. through sys.stdin.readline() or input()) and send that message to the server like you're already doing

CodePudding user response:

I think the issue is the client's for loop.

sys.stdin.readline() stops the flow until Enter is pressed, so when you send a message from client1, client2 is still waiting for the user to write its own message. Basically since the first item in read_sockets is always socket.socket() every client's first action will be to wait for user input to send a message. The server on the other hand is always listening and never waits, so it receives it immediately.

To solve this you can either have an async connection, meaning you send 1 message then wait to receive 1 message and so on, or use multithreading and dedicate a thread to receiving and one to sending.

  • Related