Server
This sends 10 floats at a time, on a loop. The transmit data type is determined by the'=%sf' % payload.size
format string passed tostruct.pack
.
import socket
from struct import *
import numpy as np
#number of floats we are sending
payload_size = 10
payload = np.linspace(0, 10, payload_size)
print('Sending {}'.format(payload))
#pack the floats as bytes
tx_pack_fmt = '=%sf' % payload.size
packet = pack(tx_pack_fmt, *payload)
HOST = '127.0.0.2'
PORT = 50007
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
#keep sending until the peer resets the connections
while True:
conn.sendall(packet)
output
Sending
[ 0. 1.11111111 2.22222222 3.33333333 4.44444444 5.55555556
6.66666667 7.77777778 8.88888889 10. ]
Client
This receives bytes on a loop. The same format string is used to unpack the bytes.
Note, that struct.unpack
expects bytes equal to the size of 10 * floats = 10 * 4
.
So we need to keep receiving bytes from socket until we get that number. We tell struct.pack
to expect data in the format:{}f'.format(expect_pkt_len)
import socket
from struct import *
#10 floats
expect_pkt_len = 10
#request 4 bytes for int data, use 2 if expecting short, 8 for long.
rx_buffer_size = 4
rx_unpack_fmt = '{}f'.format(expect_pkt_len)
HOST = '127.0.0.2'
PORT = 50007
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
# request bytes from socket stream
rx_data = s.recv(rx_buffer_size)
#if not the expected size, request more until we get them
while len(rx_data) < expect_pkt_len * rx_buffer_size:
print('Received bytes: {}, waiting for {}'.format(len(rx_data), (expect_pkt_len * rx_buffer_size)))
rx_data += s.recv(rx_buffer_size)
data = unpack(rx_unpack_fmt, rx_data)
print('Received bytes: {}'.format(data))
We can observer how the bytes are received in a stream from the TCP socket by printing out the received byte count for each loop.
output
Received bytes: 4, waiting for 40
Received bytes: 8, waiting for 40
Received bytes: 12, waiting for 40
Received bytes: 16, waiting for 40
Received bytes: 20, waiting for 40
Received bytes: 24, waiting for 40
Received bytes: 28, waiting for 40
Received bytes: 32, waiting for 40
Received bytes: 36, waiting for 40
Received bytes: (0.0, 1.1111111640930176, 2.222222328186035, 3.3333332538604736, 4.44444465637207, 5.55555534362793, 6.666666507720947, 7.777777671813965, 8.88888931274414, 10.0)
Note, if we want to send short we would change the format argument to pack/unpack and set the rx_buffer_size
to the number of bytes per number.
If we wanted to mix types, for example in a packet header and payload, we would need to specify the exact header/payload data format inpack/unpack
, calculate the exact size of the header/payload that we send/receive and then wait for those number of bytes to be received before trying tounpack
them.