简体   繁体   中英

Python select with sockets and sys.stdin

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!!

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
        '''

I just came across this while writing a unix domain socket (UDS) interface. The server socket id is used to accept incoming client connections. That is pretty much all it does. Once the client is accepted, reading uses its own file descriptor. Something like this works:

conn = None
inputReady, Null, Null = select.select(inputSockets, [], [])
for x in inputReady:
   if x == s.fileno():
     # accept incoming connect and add to poll list
     conn, addr = s.accept()
     inputReady.append(conn.fileno())
   elif x = sys.stdin.fileno():
      # read whole line and remove newline
      cmd = sys.stdin.readline()[:-1]
      ...
   elif conn and x == conn.fileno():
      data = conn.recv(msglen)
      if data:
          ....
      else:
          # connection has ended, remove from poll list and close
          if conn.fileno() in inputReady:
             inputReady.remove(conn.fileno())
          conn.close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM