3

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)?

Nityuiop18
  • 113
  • 3
  • 14
  • Which OS do you use? In Unix, you can use `select.select`. In Windows, you should use thread. Now you have another problem: you input get messed if you get message in the middle of typing. – falsetru Dec 26 '13 at 17:05
  • I am using Ubuntu. The other problems I will fix later – Nityuiop18 Dec 26 '13 at 17:09

3 Answers3

4

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
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Is there a way to do it on windows? using select.select? I dont want to use theards. – Nityuiop18 Dec 26 '13 at 20:53
  • @Nityuiop18, You can't use `select.select` (for this problem) on windows because it does only work with sockets on Windows. – falsetru Dec 27 '13 at 04:15
  • The implementation on windows may not be as clean but I think u can use 2 threads to achieve the same effect. One will only wait on user input and send to server, the other receives from server – Shravya Boggarapu Nov 24 '22 at 09:55
2

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.

Jakob Weisblat
  • 7,450
  • 9
  • 37
  • 65
1

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.

Netch
  • 4,171
  • 1
  • 19
  • 31