Search code examples
pythontelecommunication

Implementing "Simplest Protocol" pseudo-code algorithm in python


Using two different computers, I have to implement sender and receiver algorithms to send and receive frames. I'm a strong programmer, but relatively new to network programming and python. The algorithms are below.

Sender-site algorithm:

while(true)
{
    WaitForEvent();
    if(Event(RequestToSend))
    {
        GetData();
        MakeFrame();
        SendFrame();
    }

Receiver-site algorithm:

while(true)
{ 
    WaitForEvent();
    if(Event(ArrivalNotification))
    {
        ReceiveFrame();
        ExtractData();
        DeliverData();
    }

I have to implement these algorithms on two separate computers, one as a sender and the other as a receiver. I have no idea where to start or look for examples. I've done some research with little luck. If someone can supply example code or a good article on implementing this, that would be lots of help.


Solution

  • I find myself using Python's Socket Server examples. This will get you going on the SendFrame(), ReceiveFrame(), and DeliverData() routines.

    The MakeFrame() and ExtractData(), will vary widely based on how much data you're needing to send back and forth. I will try to dig up some good examples I have used in the past.

    If you're looking for a 1 stop solution, I would suggest looking into Twisted. There is a definite learning curve to it, but it might be worth it to you. Note that if you're wanting to package the Python code into an exe using pyInstaller or py2exe, Twisted may give you trouble based on a number of threads I have read.

    So after looking back through my notes, the framing aspect was a sore subject for me as I could not find any good examples to help. I instead wrote one from scratch and have (and still am) tweaking it.

    As you read up on socket programming you will surely see that just because you send all the data (socket.sendall()) does not mean that you will receive it all after the first socket.recv(). This adds some complexity to the message framing question. Due to lack of examples on the web, below I have a stripped down version of what I am using right now in several processes.

    Update
    So after further testing the under heavy / bursting I moved away from the regex and process the stream character by character which has greatly improved its performance.

    SendFrame(), ReceiveFrame(), ExtractData(), DeliverData() Examples:

    MESSAGE_FRAME_START = '@'
    MESSAGE_FRAME_END = '#'
    
    def process_raw_socket_message_stream(raw_message_stream):
        message_list = []
        cmd = ''
        last_footer_idx = message_string.rfind(MESSAGE_FRAME_END)
        cmd_str_len = len(message_string)
        byte_cnt = 0
        while (byte_cnt <= last_footer_idx):
            cmd_chr = message_string[byte_cnt]
            cmd += cmd_chr
            if cmd_chr == MESSAGE_FRAME_START:
                cmd = MESSAGE_FRAME_START
            elif cmd_chr == MESSAGE_FRAME_END:
                message_list.append(cmd)
    
            byte_cnt += 1
    
        # Remove the parsed data
        if last_footer_idx > 0:
            message_string = message_string[last_footer_idx+1:]
    
        return message_list, message_string
    
    def add_message_frames(unframed_message):
        return MESSAGE_FRAME_START + unframed_message + MESSAGE_FRAME_END
    
    def remove_message_frames(framed_message):
        clean_message = framed_message.lstrip(MESSAGE_FRAME_START)
        clean_message = clean_message.rstrip(MESSAGE_FRAME_END)
        return clean_message
    
    def process_messsage(clean_message):
        # Do what needs to be done
        pass
    
    def send_data(mysocket, payload):
        framed_payload = add_message_frames(payload)
        mysocket.sendall(framed_payload)
    
    def receive_data(mysocket, byte_size=1024):
        data = ''
        while(1):
            try: # Wait for data
                data += mysocket.recv(byte_size)
                if(data != '') and (data != None):
                    # Decode all messsages
                    message_list, remaining_data = process_raw_socket_message_stream(data)
    
                    # Process all of the messages
                    for messsage in message_list:
                        process_messsage(remove_message_frames(message))
    
                    # Store the remaining data
                    data = remaining_data
            except:
                print "Unexpected Error"