简体   繁体   中英

Non-blocking socket for server

I've checked few similar threads on stackoverflow.com and I think I might need to open non-blocking socket for my server script. Since, I'm not sure that this is the solution question title might be wrong. Let me explain what is my problem.

Server app waits for connection and once client connects it will ask for server ID, after that client will ask for server configuration and than client will send command to server to start measurement transmission. Here's simplified version of my code:

def conn_handler(self, connection, address):
    self.logger.info("[%d] - Connection from %s:%d", 10, address[0], address[1])

    sending_measurements_enabled = False
    try:
        while True:
            data = connection.recv(2048)

            if data:
                command = get_command_from_data(data)
            else:
                command = None

            if command == 'start':
                sending_measurements_enabled = True
            elif command == 'stop':
                break
            elif command == 'id':
                connection.sendall(self.id)
            elif command == 'cfg':
                connection.sendall(self.cfg)

            if sending_measurements_enabled:
                connection.sendall(measurement)

    except Exception as e:
       print(e)
    finally:
        connection.close()
        print("Connection closed")

And here is client script:

try:

    sock.sendall(get_id_command)    

    data = sock.recv(2048) # Do I need to wait for response?
    print(data)

    sock.sendall(get_conf_command)

    data = sock.recv(2048)
    print(data)

    sock.sendall(start_sending_measurements)
    data = sock.recv(2048)
    print(data)

    while True:
        sock.sendall(bytes('I do not want this', 'utf-8')) # I would like to keep receiving measurements without this
        data = sock.recv(2048)
        print(data)

finally:
    print('Closing socket...')
    sock.close()

And here is my problem:

When I run client and send command to get ID server will return ID message, then client will send command to get configuration and server will return configuration message but when I send start command server will send only one measurement and than I guess connection.recv(2048) will block execution until server gets another command. So, I added that line inside while True: loop in client script which will keep sending (unnecessary, invalid) commands and server will keep sending measurements.

How to solve this without sending commands all the time from client. I want to be able to send only one command start and server will keep sending measurements, and stop only when client sends stop command. Also, if server receives id or cfg command while sending measurements it will first send id or cfg and than keep sending measurements.

In the server loop call select.select([connection], [connection], [connection]) ( select module provides more facilities, so pick your favorite). If the socket is readable, read command and react on it. If the socket is writable (and there was a request for data), send measurements.

In case someone needs this:

def conn_handler(self, connection, address):
    self.logger.info("[%d] - Connection from %s:%d", 10, address[0], address[1])

    sending_measurements_enabled = False
    try:
        while True:

            command = None
            readable, writable, exceptional = select([connection], [], [], 0)

            if readable:
               data = connection.recv(2048)

               if data:
                   command = get_command_from_data(data)
                   print("Received command %s", command)


            if command == 'start':
                sending_measurements_enabled = True
            elif command == 'stop':
                break
            elif command == 'id':
                connection.sendall(self.id)
            elif command == 'cfg':
                connection.sendall(self.cfg)

            if sending_measurements_enabled:
                connection.sendall(measurement)

    except Exception as e:
       print(e)
    finally:
        connection.close()
        print("Connection closed")

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