Domanda

I have a problem while trying to build the client side of a chat. I just in the begining, this is my code:

import socket
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect(("10.10.10.69",1234))
while True:
    message=raw_input("your message: ")
    if(message=="quit"):
        my_socket.close()
        break
    my_socket.send(message)
    data=my_socket.recv(1024)
    print "message from server:" , data

The problem is the raw_input. When a user sends a message the other users are stacked on the raw_input so only when they sends a message too they get the new messages.

How can I fix it (without using threads)?

È stato utile?

Soluzione

As I commented, use select.select if your chat client is running in Unix.

For example:

import socket
import sys
import select

my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect(("10.10.10.69",1234))
sys.stdout.write('your message: ')
sys.stdout.flush()
while True:
    r, w, x = select.select([sys.stdin, my_socket], [], [])
    if not r:
        continue
    if r[0] is sys.stdin:
        message = raw_input()
        if message == "quit":
            my_socket.close()
            break
        my_socket.send(message)
        sys.stdout.write('your message: ')
        sys.stdout.flush()
    else:
        data = my_socket.recv(1024)
        print "message from server:" , data

Altri suggerimenti

raw_input holds up the thread it's in, so you can't retrieve messages in the same thread while waiting for it. Thus, I recommend using 2 threads, one which receives new messages (say every ten seconds) and one which sends messages (using code similar to the existing code).

If you're not committed to raw_input and are really against threads, you might want to look into the select module.

There are suggestions to use select() for stdin, but seems they aren't fixing the main problem. With select, imagine the local user is entering a line, and in a middle of this process your program outputs another user message, and, the editing of local input will be screwed. Either you don't allow to show new messages during entering the current one (why?) or screen is messed up. If you do this in a terminal, you should go using curses or some more powerful tool; with curses you can at least split input and output into different screen areas. Of course, a graphics library (like wxWidgets) is even more generally suitable for a user interface, if it's allowed in your case.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top