Rickson
Rickson

Reputation: 1090

TCP server with Python: How to optimize my implementation?

I would like to implement a TCP server using a Python script.

The server should basically do the following task:

It will be cyclically polled by a remote client, then reads certain data on its local workstation and sends it to the client polling.

One can assume the following:

Goal:

Since I have only a little experience with the topic, I would like to discuss here how my current (very simple) code could be optimized to meet the requirements previously mentioned.

So far I have the following:

import socket
import sys

port_number = 12345
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_address = (socket.gethostname(), port_number)
sock.bind(server_address)

sock.listen(1)
while True:
    connection, client_address = sock.accept()
    try:
        while True:
            data = connection.recv(4096)
            if data:
                connection.sendall(getdesireddata(data))
            else:
                break
    finally:
        connection.close()

Thank you for all your responses.

Upvotes: 1

Views: 2091

Answers (1)

Aya
Aya

Reputation: 42050

First of all, there's minor bug in the code. The line...

data = connection.recv(4096)

...will attempt to read up to 4k from a single TCP packet, but if the client sends more than 4k, or decides to break up the data into several packets, you may not get all the data in a single call.

You'd typically continue to read data from the socket, appending to a buffer, until either you have a complete message as defined by your protocol specification, or until the remote host closes the outbound half of its TCP connection.

You'll also have issues with the server getting stuck if the client crashes, and doesn't shut down the socket properly. To avoid this, you'll need to look at either non-blocking IO, which would be something like...

connection.setblocking(0)
buffer = ''
while 1:        
    try:
        data = connection.recv(4096)
        if not data:
            # Client has closed outbound connection
            break
        else:
            # Append to buffer
            buffer += data
    except socket.error, e:
        code = e.args[0]
        if code == 11:
            # Got EWOULDBLOCK/EAGAIN
            time.sleep(0.1)
        else:
            # Got another error
            raise
do_something_with(buffer)

...or look at using the Python select module to do the same thing.

With regards to the lesser concern of performance, I don't see any major improvements you can make with such a small code sample.

Upvotes: 3

Related Questions