Python select with sockets and sys.stdin

10,116

Well I know you asked this 7 years ago, but I had similar questions so I would figure I answer you. I'm still working and bugfixing a program that has the same functionality, but one thing I do know is that the lists that are the arguments in select.select() need to be file descriptors (ints).

So if you have this block

input = [s, sys.stdin]


running = 1

while running:


    print("im right before the select")
    # when there's something in input, then we move forward
    # ignore what's in output and except because there's nothing
    # when it comes to sockets
    inputready, outputready, exceptready = select.select(input, [], [])

The first thing I'd say is change your read list to not be input. You'll likely get some clashing with the input() function, which may cause confusing bugs. After that, you want the values to be file descriptors. So that first line should be

inputSockets = [s.fileno(), sys.stdin.fileno()]

Then when checking which socket is ready to ready, you would want to do it like this

for x in inputready:
    if x == s.fileno():
        # Read from your s socket
    elif x == sys.stdin().fileno():
        # Read from stdin
    else:
        '''
        Here you would want to read from any other sockets you have.
        The only problem is your inputSockets array has ints, not socket
        objects. What I did was store an array of actual socket objects
        alongside the array of file descriptors. Then I looped through the
        list of sockets and found which socket's .fileno() matched x. You could
        probably be clever and use a dict() with the filenos as key and socket as
        value
        '''
Share:
10,116
Admin
Author by

Admin

Updated on June 07, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm new to Python programming and I'm trying to create a server and a client. I still want to be able to type something from the keyboard so i can close the server from the server by typing 'exit'. I've taken samples codes from various sites to get to where I'm at in socket programming and this code.

    However, whenever I run the code I get the following error message:

    The host name of this machine is 127.0.0.1
    The IP address of the host is 127.0.0.1
    Server now awaiting client connection on port 2836
    im right before the select
    Traceback (most recent call last):
      File "/root/Server_2.py", line 42, in <module>
        inputready, outputready, exceptready = select.select(input, [], [])
    TypeError: argument must be an int, or have a fileno() method.
    >>> 
    

    I was reading around that to get passed this (in Windows) is to remove the sys.stdin because Windows only accepts sockets. I'm trying to write this code in Linux. I've tried all sorts of things to try to get it to work and I'm all out of resources and ideas to try. Below is the server code:

    import socket                       #import socket module
    import select
    import sys
    
    host = "127.0.0.1"
    print ("The host name of this machine is " + host)
    hostIP = socket.gethostbyname(host)    # get host IP address
    print ("The IP address of the host is %s" % (hostIP)) 
    port = 2836                        # Reserve the port for the server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((hostIP, port))                # This server to a port
    
    s.listen(4)                         # Now wait for client connection
    
    print("Server now awaiting client connection on port %s" % (port))
    
    #WINDOWS ONLY ACCEPTS SOCKETS FOR SELECT(), no standard in
    input = [s, sys.stdin]
    
    
    running = 1
    
    while running:
    
    
        print("im right before the select")
        # when there's something in input, then we move forward
        # ignore what's in output and except because there's nothing
        # when it comes to sockets
        inputready, outputready, exceptready = select.select(input, [], [])
    
        print("i'm here na")
        # check who made a response
        for x in inputready:
    
            if x == s:
                print(s)
                #handle the server socket
                client, address = s.accept()
                print("connection comming in")
                input.append(client)
    
            elif x == sys.stdin:
                # handle standard input
                stuff = sys.stdin.readline()
                if stuff == "exit":
                    running = 0
                else:
                    print("you typed %s" % (stuff))
    
    
            else:
                #handle all other sockets
                data = x.recv(1024)
                print("i received " + data)
                if data:
                    if data == "exit":
                        x.close()
                        input.remove(x)
                        running = 0
                    else:
                        x.send(data)
                        print("I am sending %s" % (data))
                else:
                    x.close()
                    input.remove(x)
    
    
    s.close()
    

    Any help or ideas would be greatly appreciated. Thanks!!