Communication over IP
Simple data exchange between client and server over IP.
The data is stored in a Struct
and then packed to be sent as binary data. fmt
is the description of the struct content. In the client-server example below fmt = '!I30sd'
: the ! refers to the byte-order convenction (big-endian for nework in this case), I stands for unsigned-int (4 bytes), 30s stands for 30 char (1 byte each) and d stands for a double (8 bytes).
Line
can be initialized both as a client and as a server. The server application must be launched before the client. When data is sent, the listener application runs the function action
with the data received as first argument. actionargs
can be used to share variables (in the example below it is used for a queue object).
import socket
import struct
class Line(object):
def __init__(self, fmt='!I2sd', server=True, action=None, actionargs=[], ip='localhost', port=10000):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_address = (ip, port)
self.s = struct.Struct(fmt)
self.action = action
self.actionargs = actionargs
if not((type(self.actionargs) is list) or (type(self.actionargs) is tuple)):
self.actionargs = (self.actionargs,)
if server:
self.sock.bind(self.server_address)
self.sock.listen(1)
self.connection, client_address = self.sock.accept()
else:
CONNECTION_ATTEMPTS = 5
for i in range(CONNECTION_ATTEMPTS):
try:
self.sock.connect(self.server_address)
print("Connected with server.")
break
except:
import time
print("Connection attempt "+str(i+1)+" of 5 failed.")
SLEEP_BETWEEN_CONNECTION_ATTEMPTS = 1
time.sleep(SLEEP_BETWEEN_CONNECTION_ATTEMPTS)
self.connection = self.sock
if self.action:
import threading
listener_thread = threading.Thread(target=self.listener)
listener_thread.start()
def listener(self):
while True:
dataByte = self.connection.recv(self.s.size)
if dataByte:
self.action(self.s.unpack(dataByte), *self.actionargs)
def send(self, message):
self.connection.sendall(self.s.pack(*message))
def __exit__(self):
self.sock.close()
Server:
import queue
import threading
import time
import ipcomm
def c_fun(data, jobs):
jobs.put(data)
jobs = queue.Queue()
def process_job(q):
while True:
a,b,c = q.get()
for i in range(a):
print(str(i)+": "+b.decode('utf-8'))
time.sleep(c)
fmt='!I30sd'
myServer = ipcomm.Line(fmt=fmt, server=True, action=c_fun, actionargs=jobs)
pj = threading.Thread(target=process_job, args=(jobs,))
pj.setDaemon(True)
pj.start()
Client:
import ipcomm
fmt='!I30sd'
myClient = ipcomm.Line(fmt=fmt, server=False)
while(True):
a = int(input("\nNumber of repetition: "))
b = input("String to write: ").encode('utf-8')
c = float(input("Sleep time (s): "))
myClient.send((a, b, c))
print(" >>>>>> Struct sent to the client >>>>>>")