diff --git a/python/client.py b/python/client.py
old mode 100755
new mode 100644
index 01e7c14d674d0eb28cdab04c4ff75cb42b2d2242..4df46b8c58d906bc4d35f42784be24009db81080
--- a/python/client.py
+++ b/python/client.py
@@ -21,9 +21,15 @@ socket = context.socket(zmq.REQ)
 socket.connect(SERVER)
 
 def set_pixel(x, y, v):
-  tx = bytearray(9)
-  struct.pack_into('iiB', tx, 0, x, y, v)
-  socket.send(tx)
+  tx = struct.pack('<BiiB', 0, x, y, v)
+  socket.send_multipart([tx, b''])
   rx = socket.recv()
   #print("Received reply %s [%r]" % ((x, y, v), rx))
 
+def set_pixels(pixels):
+  msg = []
+  for x, y, v in pixels:
+    msg.append(struct.pack('<BiiB', 0, x, y, v))
+  socket.send_multipart(msg + [b''])
+  rx = socket.recv()
+
diff --git a/python/gol-client.py b/python/gol-client.py
index 11f1afab6d8bccdbbcb311a3361366fb140e803a..14396c41aa489e18a7a657ff9aed4ed0b1638ba7 100755
--- a/python/gol-client.py
+++ b/python/gol-client.py
@@ -7,10 +7,12 @@ SIZE = 1
 import time
 
 def rect(x,y,w,h,r,g,b):
+    pixels = []
     for i in xrange(x,x+w):
         for j in xrange(y,y+h):
             #pixel(i,j,r,g,b)
-            client.set_pixel(i, j, r)
+            pixels.append((i, j, r))
+    client.set_pixels(pixels)
 
 def draw(x, y, v):
     rect(x*SIZE, y*SIZE, SIZE, SIZE, 255*v, 255*v, 255*v)
diff --git a/python/test-client.py b/python/test-client.py
index f9977aefe1d8ace73057d2fa5d0fd6215874e66a..a984b6f4b8b65b468c694f422cb58c8fdefa316a 100755
--- a/python/test-client.py
+++ b/python/test-client.py
@@ -1,44 +1,28 @@
 #!/usr/bin/python
 
-import sys
+import sys, client
 
-SERVER = "tcp://localhost:5571"
 XOFF = 0
 YOFF = 0
 TEXT = "Hello World!"
 
 if __name__=="__main__":
-  if len(sys.argv) >= 2:
-    SERVER = sys.argv[1]
   if len(sys.argv) >= 4:
     XOFF = int(sys.argv[2])
     YOFF = int(sys.argv[3])
   if len(sys.argv) >= 5:
     TEXT = sys.argv[4]
 
-import struct
-import zmq
-
-# Prepare our context and sockets
-context = zmq.Context()
-socket = context.socket(zmq.REQ)
-socket.connect(SERVER)
-
-def set_pixel(x, y, v):
-  tx = bytearray(9)
-  struct.pack_into('iiB', tx, 0, x, y, v)
-  socket.send(tx)
-  rx = socket.recv()
-  #print("Received reply %s [%r]" % ((x, y, v), rx))
-
 import pygame
 pygame.init()
 
 font = pygame.font.Font("/usr/share/fonts/X11/misc/5x7.pcf.gz", 7)
 text = font.render(TEXT, True, (255, 255, 255), (0, 0, 0))
 pxarray = pygame.PixelArray(text)
+pixels = []
 for x in range(text.get_width()):
     for y in range(text.get_height()):
-        set_pixel(XOFF+x, YOFF+y, pxarray[x][y])
+        pixels.append((XOFF+x, YOFF+y, pxarray[x][y]))
 del pxarray
+client.set_pixels(pixels)
 
diff --git a/python/test-server.py b/python/test-server.py
index a2b920f025e824b33ce56c9fd140612c3b9fa6b7..89ef86b193d6a184bbddc5392d1b5d36b13e5359 100755
--- a/python/test-server.py
+++ b/python/test-server.py
@@ -42,8 +42,24 @@ while True:
         pygame.display.update()
         continue
 
-    message = socket.recv()
-    x, y, v = struct.unpack_from('iiB', message)
-    # print("Received request: %r, %r, %r" % (x, y, v))
-    set_pixel(x, y, v)
-    socket.send(b"")
+    messages = socket.recv_multipart()
+    #print("New multimessage")
+    for message in messages:
+        if not message:
+            break
+        cmd, = struct.unpack_from('<B', message)
+        #print repr(message)
+        if cmd == 0: # set pixel
+            cmd, x, y, v = struct.unpack_from('<BiiB', message)
+            #print("Received set pixel: %r, %r, %r, %r" % (cmd, x, y, v))
+            set_pixel(x, y, v)
+        elif cmd == 1: # blit
+            cmd, x, y, w, h = struct.unpack_from('<Biiii', message)
+            #print("Received blit: %r, %r, %r, %r, %r" % (cmd, x, y, w, h))
+            for r in range(h):
+                for c in range(w):
+                    set_pixel(x+c, y+r, ord(message[17+r*w+c]))
+        else:
+            cmd, = struct.unpack_from('<B', message)
+            print("Received unknown: %r" % (cmd,))
+    socket.send(b'')