16. Tutorial: Network coding
16.1. Sockets
A socket connects a program on one computer to a program running on another computer. One program writes data into its socket. The data may be raw bytes, or any of the datatypes we have seen (e.g. integer, string, etc.) The data travels across the network. The program on the other computer reads the data from its socket.
Connecting a socket is a bit like making a phone call. The program that is waiting to receive the call is the server. The program that makes the call is the client. Once the call is connected they can both speak to each other.
If possible, you should run the server program on one computer and the client program on a different computer, both connected to the same network. If you don’t have two computers you can run both programs on the same computer. Using Mu, you will have to load two copies of Mu in order to run two programs at the same time.
First find out the IP address of your server computer and write it down. The easiest way to open a command terminal and type a command. Possible commands:
ipconfig
(Windows)ifconfig
(Mac)ip address
(Linux)
The IP address will look similar to this: 192.168.0.105
Enter and run the server program:
1import socket
2
3sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4sock.bind(("0.0.0.0", 65439))
5while True:
6 sock.listen()
7 connection, address = sock.accept()
8 message = connection.makefile().readline()
9 print("received: ", message, "from:", address)
After creating the socket, we bind() it to an internet address. 0.0.0.0 is a special address that means “any address belonging to this computer”. We also give a port number, 65439. This can be (almost) any number, but it must match on the client and server.
Then we listen(), which pauses the program until a connection arrives. Then we read a line from the socket connection and print it out.
Enter and run the client program. We have put the address of the server in a variable. If your server is on a different computer, use the address of that computer. If it on the same computer, use the special address 127.0.0.1.
1import socket
2
3server = ("127.0.0.1", 65439)
4sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5sock.connect(server)
6sock.send(b"hello")
7sock.close()
8
Note that we send a string, but we prefix it with b to convert it into bytes. We close the socket after we are finished to end the connection.
You should see the string appear on the server program output.
Exercise
Send a different message from the client to the server.
Exercise
Make the client program ask the user to input a message, and then send it to the server. Make a loop so it keeps asking and sending.
16.2. Gopher
Gopher is a hypertext system, similar to the World Wide Web. However Gopher is older than the web, and its protocol is simpler, which makes it easier for us to implement. A protocol is just an agreement between the client and server on what sort of data they are allowed to send and receive.
We are going to write a Gopher client, connect it to a Gopher server, and see if we can figure out the protocol.
1import socket
2server = ("gopher.floodgap.com", 70)
3sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4sock.connect(server)
5sock.send(b"\r\n")
6for line in sock.makefile().readlines():
7 print(line)
8sock.close()
9
You can change the server to connect to any gopher server, but we are using gopher.floodgap.com because it is popular.
When you run the program, it simply sends “\r\n” which means a return followed by a newline. It then prints the lines it gets back from the server. You should get some output that looks a bit like this:
iWelcome to Floodgap Systems' official gopher server. error.host 1
iFloodgap has served the gopher community since 1999 error.host 1
i(formerly gopher.ptloma.edu). error.host 1
This is readable, but we can improve it. You might notice that every line starts with a special character, usually an i (meaning info). This isn’t part of the text, so we will chop it off.
Python lists and strings allow us slice them up. For example, if you have a string
s = "Hello"
Then these some slices you could make:
s[0] == "H"
s[1] == "e"
s[0:4] == "Hell"
s[1:] == "ello"
s[:2] == "He"