Listening on a Socket
00:00
In the previous lesson, I used Wireshark to show you what happens inside of TCP/IP. In this lesson, I’ll introduce Python’s socket
library.
00:09
The socket
module in Python is a thin wrapper to the equivalent C library. That means it’s rather low level and not the friendliest thing. Even the documentation’s a bit harder to grasp than other Python docs.
00:23 It’s still comprehensive, but it has the expectation that you know what all this socket stuff is.
00:29 For the most part, when someone says open a socket, they typically mean connect to another machine through the network, but sockets can be used for other kinds of communication as well.
00:39
As such, if you want the network variety, you have to say that when you create the socket. The AF_INET
constant means use IP version 4, while SOCK_STREAM
says you want to use it as a stream of data.
00:53 Using a socket as a server requires a bit of setup. There are five steps. First, you create the socket itself, specifying those two constants I just mentioned.
01:03 Then you have to bind to a host and port. Since I’m using TCP/IP, the host can be a hostname or an IP address, and the port is the service port on the remote machine.
01:14
For most of this course, I’ll be sticking to an IP address. I’ll talk about hostnames later and how they can add complications. Once you’ve got the address bound, you call the listen()
function to say you want to take a connection and then you call accept()
to accept a connection.
01:30
For our simple case, this seems like it could just be done in one step, but listen()
is a non-blocking call and in fancy configurations you can use it to limit just how many different things can be listened to, while accept()
is a blocking call that waits until someone actually connects to you.
01:46 At this point, your code waits until somebody opens a socket to your port, and once they do, you can then send and receive data over this socket.
01:56 For our first socket program, I’m going to implement a “bork” server. This is a variation on an echo server. It listens to a socket and whatever it receives on the socket, it echoes back down to the sender, appending, bork, bork, bork to the end.
02:11 If that seems like nonsense words to you, Google “Muppets, Swedish Chef” and have a smile. You’re welcome. Eventually, I’ll show you how to write some client code as well, but for now, let’s concentrate on the server.
02:24 That means I’ll need some way to connect to it.
02:28 Curl is a command line data transfer tool typically used to fetch a web page. It essentially is a socket client that implements a whack load of application protocols, including the web, FTP, mail stuff, and much more.
02:41 One protocol it supports is TELNET. This is an older protocol that shouldn’t really be used much anymore. It’s a plain text connection to a remote machine and used to get used for logging into servers.
02:53 As it’s plain text, nefarious people can see what you’re doing, so TELNET is mostly a historic artifact at this point. You should be using SSH instead, but as it is a simple way of sending stuff down a socket, it suits our purposes just fine.
03:11
And this is the code for the bork server. To start out, you need to import the socket
library. Once you’ve got the socket, you’ll need to say what interface you want to listen on.
03:21 You do that with an IP address, which I’m putting in a constant here.
03:26
Remember, 127.0.0.1
is the loopback interface, which means it will only be local to your own machine. This has the added benefit of not being blocked by firewalls and various things.
03:38
To go with our address, I need a port. I’ve picked something high up in the ephemeral range so as not to interfere with other protocols. The socket()
function in the socket
module creates a socket object.
03:50
As I mentioned before, you have to tell it what kind of socket this is going to be, which in this case is a TCP/IP data stream. The context manager gives me the actual instance, which I’ve named s
.
04:02 The big advantage of a context manager here is it will close the socket for you.
04:07 Remember, there are five steps. Binding to the address and port is step two, and then listening is step three. Once I’ve listened, I accept a connection. This blocks until someone actually connects with a socket.
04:20
The accept()
method returns two things, a handle to the connection and a tuple containing the IP address and port of the connector.
04:28
Remember from previous lessons that the client automatically gets its own ephemeral port number when it connects to the server. Once the connection is going, I loop and use the recv()
method to get some data.
04:40
You have to tell recv()
how much data you’re willing to take, and here I’m asking for a kilobyte. Note that the client is allowed to send less than that and if you send more, the next chunk won’t get read until another iteration of this loop.
04:53
I’ll show you more about this with larger blocks of data in a future lesson. If the client disconnects, the recv()
function returns empty. Here, I break out of the data receiving loop, meaning the socket gets closed.
05:05 Our server isn’t particularly friendly, it only accepts one connection and then shuts down. More on that later.
05:13
If the data isn’t empty, I strip out any carriage returns, then append, `bork, bork, bork, and use
sendall()` to fire the content back at the client.
05:23
Note that the bork, bork, bork
is binary. That’s important. I’ll dive into that later as well. Finally, as something could go wrong in all of this, I want to catch any exceptions.
05:34 That way the context manager is guaranteed to exit cleanly and close the socket. If your program crashes, it takes a little bit of time before the OS bothers to clean up your socket, so you might find you can’t reestablish a connection because the port is already taken. Cleanly closing your socket prevents this from happening.
05:52
Let’s try this out. In the top window here, I’ll run our server, and in the bottom window I’m going to use curl
to connect to the server. Two things, I’m going to use the -s
option for silent. By default, curl
shows you a progress bar for the data connection, which just gets in the way for our situation.
06:13 And two, like I mentioned, I’m going to use TELNET. I do that by forming a URL that starts with the TELNET protocol and then has the IP and port of our server.
06:27 In the top window, you can see the print info that shows a connection has been made. Note that the port number is 64543. That’s the automatically assigned port for the client.
06:38 This threw me at first as many of the digits are similar to 65432, which is where the server is listening, but that’s just a coincidence. Let me type something. When I pressed Enter in the client, the Hello got received by the server, which replied back with the borky version.
06:55 Once more for giggles, and there you go.
07:01 On the client side, I’ll hit Control-C to close the connection and note that the server got the empty data chunk and exited the program.
07:10 Now that you’ve got the bork server, in the next lesson I’ll show you how to see what is connected.
Become a Member to join the conversation.