Tying to Application Server
00:00 In the previous lesson, I outlined an application protocol. In this lesson, I’ll take our message mechanism from before and tie it into a server.
00:09 I want to write a bit more code before sticking this in a server. I want to make sure that the serialization works properly, so I’ll start by writing some tests.
00:18 Then, once confident that the message code works, I’ll use a selector-based structure similar to the multi-bork server that accepts and prints messages. And then of course, I need a quick client that sends messages to make sure all of this works.
00:32
This is my test harness. I start out by using the message factory to create a new message, and then create a MessageProcessor
state machine. In the server, this is what will be associated with a connected socket. In my tests, I’m just going to use it directly.
00:48
The first test calls the state machine’s receive_bytes()
method sending in all the bytes from the factory. If everything is working, the result back should be a message object, which evaluates as equal to the original one.
01:01 That first test is one end of the spectrum, all the bytes fitting in a single packet. Now let’s go to the opposite extreme, sending a single byte at a time.
01:10
Here I iterate over the message bytes, calling receive_bytes()
with each byte individually. Once the loop is done, the last call to receive_bytes()
should result in the new message object, which should evaluate as equivalent to our original.
01:25 Let me scroll down. The second half of this test is almost identical to the first half, except this time the message content is binary rather than text. Then I do a similar all at once and then a byte at a time test.
01:40 Yep. I could have created a function for this, but sometimes you just copy and paste. This time was sometime, evidently.
01:49 Take my word for it that I ran those tests and they passed. What’s on the screen now is an application server. What this server does is receive messages and print them to the screen.
02:00 The structure of this code is almost identical to the multi-bork server using a selector to manage multiple connections. Here’s the first difference. In multi-bork, I used a simple namespace to store the state associated with the selected connection.
02:14 Here, I’m using our message processor object instead.
02:21
And this is the other difference. When data is received, I call the message processor’s receive_bytes()
method, which either returns None
if it isn’t done yet, or a message if a complete message is available. In the real world, you’d now do something with the message. In my toy world, that something is simply printing it out.
02:40
In the previous lesson, when I covered the message object itself, I skipped past the fact that I had defined a dunder __str__()
method. Having that means the print will show some formatted content.
02:54
Okay, that was the server. This is the client. Our client sends two messages, but to ensure things are working, I’m using very small chunk sizes for our data so that it takes multiple calls to sendall
to get the entire message to the server.
03:09
I’m also going to add some sleep calls to slow the whole thing down. This is my chunk size. I’ve set it to a very low value of 20 bytes. Once I’ve got the socket ready, I use the message factory and call its to_bytes()
method, then loop through the resulting byte data, a chunk at a time, waiting for one second after each send. Then just for fun, I do it again, this time with some binary content for our message.
03:34 Instead of text, let’s go use this code.
03:39 We’ll start the app server up,
03:43 and now in the bottom window, I’ll start the client.
03:48 Same time dilation technology going on here as in previous lessons. The client connects to the server, which you can see the connection message and associated sending ports.
03:58 Then the server receives some bytes, then 20 more, then 20 more, and then the last six. It has everything it needs to fully construct a message, which it receives, and then prints out. Now for the Gonzo part: 20 bytes, 40,
04:19 19 more, and a decoded message. And there you have it, an application-level protocol.
04:27 I’ve made a lot of assumptions along the way. So next up I’ll talk about just what kind of a donkey umptions can be.
Become a Member to join the conversation.