1

In an attempt to get a chat system working in Python using Windows, I have used the following code on the client-side:

chat_client.py

import sys, socket, select

def chat_client():
    if(len(sys.argv) < 3) :
        print 'Usage : python chat_client.py hostname port'
        sys.exit()

    host = sys.argv[1]
    port = int(sys.argv[2])

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)

    # connect to remote host
    try :
        s.connect((host, port))
    except :
        print 'Unable to connect'
        sys.exit()

    print 'Connected to remote host. You can start sending messages'
    sys.stdout.write('[Me] '); sys.stdout.flush()

    while 1:
        socket_list = [sys.stdin, s]

        # Get the list sockets which are readable
        read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])

        for sock in read_sockets:            
            if sock == s:
                # incoming message from remote server, s
                data = sock.recv(4096)
                if not data :
                    print '\nDisconnected from chat server'
                    sys.exit()
                else :
                    #print data
                    sys.stdout.write(data)
                    sys.stdout.write('[Me] '); sys.stdout.flush()     

            else :
                # user entered a message
                msg = sys.stdin.readline()
                s.send(msg)
                sys.stdout.write('[Me] '); sys.stdout.flush() 

if __name__ == "__main__":

    sys.exit(chat_client())

However, I am getting the following error when attempting to connect to a server (which is running in Python too):

select.error: (10038, 'An operation was attempted on something that is not a socket')

This has something to do with sys.stdin.

I believe this is issue with file objects on Windows not being acceptable, but sockets are. On Windows, the underlying select function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.

Is there a workaround to this to allow for a way to implement the chat_client.py code on Windows?

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
Sagar Mohan
  • 145
  • 1
  • 5
  • 17
  • ...don't try to use stdin as if it were a socket? Not sure what kind of answer you're expecting here. – Charles Duffy Jan 30 '17 at 17:42
  • Lots of ways to implement the "don't do that" approach. One is multithreading -- if you have a separate thread reading from stdin, it can do the easy thing and use a blocking read call, while your network code uses `select()` and `recv()` (the latter of which is likewise a socket call not expected to work with stdin). – Charles Duffy Jan 30 '17 at 17:43
  • Plenty of existing questions this overlaps. See for example http://stackoverflow.com/questions/10842428/can-select-be-used-with-files-in-python-under-windows and http://stackoverflow.com/questions/12499523/using-sys-stdin-in-select-select-on-windows?rq=1 – Charles Duffy Jan 30 '17 at 17:44
  • Thanks for your comments Charles. I'm attempting to follow this guide to making the chat application: http://www.bogotobogo.com/python/python_network_programming_tcp_server_client_chat_server_chat_client_select.php I used multithreading before, and I've had a look at the questions you've listed however I wasn't able to get a definitive solution. – Sagar Mohan Jan 30 '17 at 17:50

1 Answers1

1

Is there a workaround to this to allow for a way to implement the chat_client.py code on Windows?

You could manage with periodical checking of input activity, e. g. by replacing your select statement with

        # Get the list sockets which are readable, time-out after 1 s
        read_sockets = select.select([s], [], [], 1)[0]
        import msvcrt
        if msvcrt.kbhit(): read_sockets.append(sys.stdin)

Note that in this example approach, when one began typing in a line, incoming messages will only be displayed after the input line is finished.

Armali
  • 18,255
  • 14
  • 57
  • 171