Socket Server

Problem #416

Tags: python c-1 practical special

Who solved this?

No translations... yet

This problem is heavily tech-oriented, skip it please if you feel aversion to such exercises.

There are two most common ways of exchanging data in computer networks, namely TCP and UDP. The first of them underlies the familiar HTTP for example, i.e. the most of WWW functions with its help. Let's have a closer look.

With both protocols one side, the server is working continuously, listening for incoming requests. The other side, client (usually, many clients) may start and stop at random, sending to or requesting from server whenever they want. Addressing requires server address and port number. In this way, many servers may run on the same address but on different ports. Most popular usage for it is seen when some website (like this one) could be accessed via plain HTTP (on port 80) or via encrypted HTTPS (on port 443).

So to start the server we only specify the port to listen on. Actually some auxiliary settings could be specified, for example it is possible to limit from which addresses we accept requests. But in simple cases it is all right to accept from any address.

When client wants to exchang with the server, it should specify both address and port. And next comes the difference between UDP and TCP:

Here is a live example (actually coming from one industrial project I worked for in the past). There is a LoRaWAN server which collects data sent by various sensor and devices through gateways. These gateways are small things similar to WiFi router - they get wireless data from the sensor (in LoRa protocol) and then retransmit them over conventional internet in form of UDP packets.

Why UDP is chosen here? because neither sensor nor gateway really cares whether data were received or not. They could be lost even in the air, before reaching the gateway - thus no sense in any further checks. And anyway, if (hypothetically) device or gateway is able to figure out when packet is lost -what should it do? No, there is no any obvious logic to follow. Thus UDP being much more lightweight protocol, suits ideally.

However, data are somehow collected/aggregated by the server and now we want to work with them - this is done by user requests sent over TCP (and actually in HTTP or GRPC form).

In the program code both sending and receiving interface is called socket - we say that we open server socket at the given port to listen - and on the other side we create client socket to send / connect to server.

The problem

Write a server code which listens both for UDP and TCP. When UDP packet comes, it is simply expected to contain integer value - you need keep total count of such packets - and sum of values in them.

Meanwhile TCP socked could be used by client to send request of any of 3 types:

The numbers of ports to be opened for listening are passed via environment variables named TCP_PORT and UDP_PORT respectively.

For example, suppose that server has just started and the following exchanges happen:

How to start with it

While it is not the only way, but you may look at socketserver package of python standard library. Scroll the page down to "Example" of TCP server - here we get it in slightly shortened form:

import socketserver

class MyHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024).strip()
        print('Got request with: ' + str(data, 'ascii'))
        self.request.sendall(data.upper())

server = socketserver.TCPServer(('localhost', 9999), MyHandler)
server.serve_forever()

Start this program, it will print nothing yet - it just waits for requests. Go to the other console window and send something using telnet program (which is usually installed by default in linux and OsX, but could be disabled in windows - google about enabling it or download handy putty program instead).

telnet localhost 9999

Generally "localhost" is defined somewhere to be substitued with address 127.0.0.1 which means "this same machine". Thus the following interchange may occur:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello world                                     <-- only this line is typed in by user
HELLO WORLDConnection closed by foreign host.

Meanwhile you'll see Got request with: hello world in the window where server is running. You can connect with telnet multiple times.

Now you only need to improve this program:

When you submit your code, it is checked by really creating several requests to it so you'll see various verdicts depending on how well your server behaves. Keep in mind that checking system couldn't usually tell what exactly causes the specific error as it only "sees" it from client side.

You need to login to get test data and submit solution.