Network programming for PyS60 (XV)

by Marcelo Barros

As discussed in post III, TCP sockets have flow control but they require some extra coding since we can not precisely control the amount of received bytes when using recv(). However, the socket API in Python provides a very useful method called makefile() that transforms a standard socket object in a file like object. For instance, you can use read() to receive a specific amount of bytes or readline() to receive a complete line (for line oriented streamings, of course). It is important to note that this file like object not is common in other socket API even though it is very interesting and frequently used in Python applications. In this post I want to show some examples using makefile.

In this first example a “line oriented client/server” is presented. First, take a look in the client. It is used to send five lines to server through the file like object. An special call to flush() is necessary to send any pending byte before slepping (time.sleep() call) and the newline character (\n) is required. The newline is used to control the flow and it is not removed from the streaming at server side.

import socket
import time
 
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(('127.0.0.1',54321))
 
fsock = sock.makefile()
for i in range(5):
    msg = u"Sending line %d ...\n" % i
    fsock.write(msg)
    print msg
    # call flush to send pending bytes
    fsock.flush()
    time.sleep(1)
sock.close()

The server is really simple as well, as you can see below:

import socket
 
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',54321))
s.listen(1)
while True:
    sock,addr = s.accept()
    fsock = sock.makefile()
    print "New connection from",addr
    while True:
        line = fsock.readline()
        if not line:
            print "Connection closed"
            break
        print "=> ",line

A better and more interesting example may be created when we need to decode headers or specific protocol issues. Suppose we have created a protocol where the first two integers (each one with four bytes in big endian format) are version and size, respectively. After them, the data is transmitted. See how this could be done using makefile (client and server are below):

import socket
import struct
import random
 
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(('127.0.0.1',54321))
 
fsock = sock.makefile()
# creating a random header
version = random.randint(0,5)
size = random.randint(0,10)
header = struct.pack('>LL',version,size)
print "Version:",version
print "Size:",size
fsock.write(header)
data = 'X'*size
print "Data:",data
fsock.write(data)
fsock.flush()
sock.close()
import socket
import struct
 
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',54321))
s.listen(1)
while True:
    sock,addr = s.accept()
    fsock = sock.makefile()
    print "New connection from",addr
    # decoding header
    header = fsock.read(8)
    (version,size) = struct.unpack('>LL',header)
    print "Version:",version
    print "Size:",size
    data = fsock.read(size)
    print "Data:",data
    sock.close()

We had a lot of work in post VII for decoding a “homebrew” protocol to receive files over WiFi, remember ?

That’s all. And sorry for the long time for publishing this post but I was traveling on vacation.

Related posts:

  1. Network programming for PyS60 (IX) A new element was presented in our last post: exception...
  2. Network programming for PyS60 (XIII) In our last post we talked about multicast, a special...
  3. Network programming for PyS60 (VIII) Did you do your homework ? So, I would like...
  4. Network programming for PyS60 (VII) Everything is about “protocols” in computer networks, doesn’t it ?...
  5. Network programming for PyS60 (XII) Until now we have used only TCP in our examples...

Related posts brought to you by Yet Another Related Posts Plugin.