Source

python-socket-examples / slideshow.md

Full commit

Sockets?

  • This talk isn't really about sockets
  • (well not entirely)
  • now that is cleared up lets get sockets out of the way...

Network Sockets

The rather normal network socket:

import socket
tcp_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
tcp_socket.connect(("google.com", 80))
tcp_socket.sendall(b"GET / HTTP/1.1\r\n")
  • A not so distant cousin to how your browser kicks off a request...
  • Let's take a look at the normal client/server example for network sockets

Server

def echo(conn):
    while True:
        data = conn.recv(1024)
        if not data: break
        conn.send(data)
    conn.close()

def consumer_server(...
    s = socket.socket(address_family, socket_type, protocol)
    s.bind(
    s.listen(5)
    while True:
        conn, addr = s.accept()
        threading.Thread(target=echo, args=(conn,)).start()
  • listen(5) tells the OS to queue up to 5 connection requests
  • Note a new thread gets spun up for every client connection
  • Threads spin up plenty quick
  • Yes all the error handling has been removed to ease readability at the expense of all usability..

Client

af, socktype, proto, _, sa = socket.getaddrinfo(
    host, 
    random_port, 
    socket.AF_UNSPEC, 
    socket.SOCK_STREAM)[0]
s = socket.socket(af, socktype, proto)
s.connect(sa)
s.sendall(outgoingdata)
  • Leaving the address family unspecified will return INET and INET6

Demo

Meet the Freerunner - open source phone running SHR (debian based)

ssh root@192.168.7.2

cd code
cat server.py
python server.py
  • Well it would be a bit boring just running on my laptop!

  • Incase I forget run on the pc: python3 basic_socket_client.py

Unix Sockets

So on GNU/Linux everything is a file. This includes everything from .txt files to Sockets.

  • TCP/UDP sockets can connect endpoints on the same network

  • Unix Sockets can only connect endpoints on the same machine.

  • This lets the Kernel make some assumptions and cut out the
    expensive "networking" layer.

Unix Sockets

They are extensively used for Inter Process Communicaton, including internally in Python's multiprocessing.connection module:

# A higher level module for using sockets (or Windows named pipes)
#
# multiprocessing/connection.py
  • From Python 3.3 Unix Sockets can also be used to send open file descriptors (open files or sockets) to another Process using the sendmsg() and recvmsg() calls.

Socket (ab)use

  • What if you were running your python program on a cretin system that didn't give you enough memory?

  • But you knew the kernel had access to plenty more...

  • You could fire off a socket and use it as some FIFO form of memory storage...

Extremely Contrived Example

  • Main thread wants to "save some data" out of process memory by creating a local socket with a large buffer
  • the consumer thread just creates the socket/s
  • to illustrate the concept my worker thread isn't allowed to access this memory (read from socket) until all the data has been stored
  • sha256 on the bytes saved and recalled should match

example socket_memory.py output

Connected by ('127.0.0.1', 45527)
waiting for producer to finish filling the socket
"Saved" 250 blocks of 2048 random bytes
SHA256 of sent: 290491d7b26ab55cf62cf9ea662634b0bd63509dfbaf02877aab458a161a5fd9
okay lets have your data
Received 250 x 2048 bytes of data
SHA256 of recv: 290491d7b26ab55cf62cf9ea662634b0bd63509dfbaf02877aab458a161a5fd9
  • No I'm not really serious, but it did appear to work...

New toy

The much awaited Rasberry Pi! + actually I'm still waiting for mine + easily fitted with a USB bluetooth dongle + actually just another computer... + which is a bit boring + need something more fun

New(er) toy!

iRacer from sparkfun

  • on-board Bluetooth radio
  • RFCOMM Bluetooth...
  • Protocol is dead easy - 0xXY where X is the direction and Y is the speed. E.G 0x16: Direction=Forwards, mid-speed.
  • https://www.sparkfun.com/products/11162

Bluetooth

One mention of "bluetooth" on the Python 3.3 socket docs... + How hard could it be... + Okay I had to use the source but the end result is easy!

import socket
import time

class BluetoothCar:
    def __init__(self, mac_address="00:12:05:XX:XX:XX"):
        self.socket = socket.socket(
            socket.AF_BLUETOOTH, 
            socket.SOCK_STREAM, 
            socket.BTPROTO_RFCOMM)

        self.socket.connect((mac_address, 1))

    def forwards(self, duration=1.0):
        self.drive(0x16, duration)
    ...

    def drive(self, command, duration):
        self.socket.send(bytes([command]))
        time.sleep(duration)
        self.socket.send(bytes([0x00]))

CAN

TODO...