Writing a server using stream socketsΒΆ
Make a Controller object.
1 | 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.
2 3 | 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.
4 | 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.
5 | addr = conn.parse_headers()
|
Now we have the connection and the address. Pass them to a handler.
6 | 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?')
conn.close()
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)
sock.close()