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:
- Network programming for PyS60 (XIII) In our last post we talked about multicast, a special...
- Network programming for PyS60 (VII) Everything is about "protocols" in computer networks, doesn't it ?...
- Network programming for PyS60 (IX) A new element was presented in our last post: exception...
- Network programming for PyS60 (VIII) Did you do your homework ? So, I would like...
- 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.