Writing a server using stream socketsΒΆ

Make a Controller object.

controller = Controller()

Create our Destination. Our Destination is our “IP Address” in the I2P network.

Our Destination instance will be discarded once it gets garbage collected, so we should keep the reference to it, and use it in a context manager.

with controller.create_dest() as our_dest:
    print('Server address: ' + our_dest.base32 + '.b32.i2p')

Tell SAM we need to accept connections. The method our_dest.register_accept tells SAM to accept connections. The return value conn is a socket object. This method will not block.

    conn = our_dest.register_accept()

SAM will write to the conn socket only when a data stream comes in. Wait until a message comes in. When a message came in, read and strip the SAM response headers.

The method conn.parse_headers will block until a message comes in.

Now a message comes in, but first we need to strip the SAM headers.

    addr = conn.parse_headers()

Now we have the connection and the address. Pass them to a handler.

    handler(addr, conn)

Write the handler.

def handler(addr, conn):
    # now we can read the real message
    request = conn.recv(4096)
    print('Received a message from %r: %r' % (addr, request))
    # reply
    conn.sendall(b'Hello, how are you?')

Write our client:

def send(server_addr):
    # test SAM connection
    controller = Controller()

    with controller.create_dest() as our_dest:
        # connect to a remote destination and send our message
        sock = our_dest.connect(server_addr)
        # SAM will give us response headers
        # when the connection is successful
        sam_reply = sock.parse_headers()
        # now we can send data
        sock.sendall(b'Hello, there!')
        real_reply = sock.recv(4096)

        print(sam_reply, real_reply)