1

Topic: Python Server Example

Hi all-

Included here is an example of creating a TCP/IP server in Python for nion/nControl. This script demonstrates how to create a simple server in Python that can be interrupted correctly when the role is stopped.

This script uses non-blocking socket techniques and assumes it is being run in a threaded python block. The server does nothing more than accept a connection and calculate the rate at which data is being received on the connection. Hopefully this will serve as a template for those looking to do something similar.

Thanks-
Frank Vernon

 
import socket
import select
import time

#Example of a simple tcp server using non-blocking sockets in a threaded script.
# The combination of threaded script and non-blocking sockets ensures that
# this script can be interrupted correctly when stopping the role (e.g. when
# redeploying your project.) 

#The server accepts only a single connection at time. It receives data until the
# client either closes the connection or stops sending data for more than 2 seconds.
# While receiving data it calculates the bit rate and outputs it on outputs[0].

port = 6511

#Create socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#bind to our desired port (on any available address)
server_socket.bind(('', port))

#set to non-blocking operation
server_socket.setblocking(0)

#main loop for the threaded script
while not event.wait_should_exit(1):
    message.string_set("Waiting for a connection...")
    outputs[0].value_set(0.0)
    
    #listen for incoming connection requests
    server_socket.listen(1)
    
    #use select to determine when a connection is available
    server_rfds, server_wfds, server_xfds = select.select([server_socket], [], [], 2)
    if server_socket in server_rfds:
        #accept the connection
        connection, address = server_socket.accept()
        
        #make new connection non-blocking
        connection.setblocking(0)
        
        message.string_set("connected")
        
        #loop receiving data and calculate bit rate
        start = time.time()
        bitrate = 0.0
        data_bits = 0.0
        while not event.wait_should_exit(1):
            #use select to wait for data on connection, timeout after 2 seconds
            conn_rfds, conn_wfds, conn_xfds = select.select([connection], [], [connection], 2)
            
            #break on error
            if connection in conn_xfds:
                break
            
            #check for data received, calculate bit rate
            elif connection in conn_rfds:
                data = connection.recv(1024)
                if len(data) == 0:
                    break

                #calculate average bit rate in Mbps
                data_bits += len(data) * 8.0
                timediff = time.time() - start
                if timediff > 0.0:
                    bitrate = (data_bits/timediff)/1000000
                outputs[0].value_set(bitrate)
            
            #break if we have a timeout condition
            else:
                break
        
        #close the inbound connection
        connection.close()

#close the server on exit
server_socket.close()
message.string_set("not running")

Last edited by fvernon (2011-01-05 22:33:39)