Skip to content

Session 10: Client_Server

Juan Gonzalez-Gomez edited this page Mar 2, 2020 · 27 revisions

Session 10: Client-Server

  • Time: 2h
  • Date: Tuesday, March-03th-2020
  • Goals: *

Contents

Introduction

We already known the basic communication mechanism between two applications located in different computers. Each of them is identified with the IP and PORT. We use the abstraction of sockets. These are objects that has some methods for allowing the communication. The bytes written to one socket are received on the other side, and vice-versa

The way the twos apps behaves in the communication depends on the model used. In the client-model, the initiative of the communications relies on the client, while the server is just waiting for clients to connect

We saw in the previous sessions that the client uses only one socket to connect to a server

In the case of Servers they need two sockets: One for listenning to the connections from the clients, and the other for transferring the data from/to the client, once the connection has been established

The communication process between the client and server is as follows:

  • Step 1: Initial state

    • The client has created a socket
    • The sever has created a socket and configured it in listening mode
  • Step 2: The client start the connection (calling the connect() method in the socket)

  • Step 3: The server creates another socket for communicating with the client

  • Step 4: The client and the server communicates normally, using the "blue" sockets. The "red" socket continues listening for new connection from other clients

Connection of many clients to the server

What happens if another client tries to connect to the server when it is already connected to the previous client?

The clients connect to the first socket, the one that is in listening mode. Typically, whenever there is a new connection, the server creates a copy of itself (we call it a fork, or a thread) that attends the client using another socket

Depending on the capacity of the server, it could attend more or less clients. If the server is busy and it cannot attend more clients, the listening socket will put the requests in a queue. They will be attended when the server finished with the previous clients

In the servers we are developing in this subject, we will only attend one client at a time, for simplicity

Introduction to the programming of servers

We will learn the basic ideas used for programming a simple server

Setting up a server

The steps that should be followed to setup a working server are:

  • Step 1: Create the socket (Method socket())
  • Step 2: Configure the socket: bind it to the remote IP and PORT (Method bind()
  • Step 3: Configure the socket in listening mode (Method listen())
  • Main loop:
    • Step 5: Wait for a client to connect (method accept())
    • Step 6: When a client connects, the socket library creates a new socket for communicating with the client
    • Step 7: Read the client messages. What does the client want? (metho rcv)
    • Step 8: Process the request and send a response message (method send)

Happy server :-)

Let's write our first server. We will call it happy server, as it is always sending us a message no matter what is the request from the client

Create the Session-10 folder in your working repo. Our server will be programed in the happy-server.py file

We will write our server from scratch. Make sure you understand all the parts

Initial configuration

This is the version 1. We create the socket, bind it to its IP and PORT parameters and configure it for being a listening socket. Finally we close the socket

import socket

# Configure the Server's IP and PORT
PORT = 8080
IP = "192.168.1.45"

# -- Step 1: create the socket
ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# -- Step 2: Bind the socket to server's IP and PORT
ls.bind((IP, PORT))

# -- Step 3: Configure the socket for listening
ls.listen()

print("The server is configured!")

# -- Close the socket
ls.close()

This server will be running in your computer. Makes sure that your IP address is correct.

Run it. You will see the message we have printed and nothing more. It just finished ok

The server is configured!

Process finished with exit code 0

If you have not configure the right IP you will see a message in red like this:

Waiting for connections

Once the server is correctly configured, we wait for connections from the client. It is done by calling the accept() method on the listening socket (ls)

import socket

# Configure the Server's IP and PORT
PORT = 8080
IP = "192.168.124.179"

# -- Step 1: create the socket
ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# -- Step 2: Bind the socket to server's IP and PORT
ls.bind((IP, PORT))

# -- Step 3: Configure the socket for listening
ls.listen()

print("The server is configured!")

# -- Waits for a client to connect
print("Waiting for Clients to connect")
ls.accept()

print("A client has connected to the server!")

# -- Close the socket
ls.close()

Run it. You will see this message on the console:

The server is configured!
Waiting for Clients to connect

The program no longer finish (like before). Now it waits for the clients to connect. You can test it with some of the clients you did in Practice 2, or you can directly use the nc command from the linux console:

$ print "Test" | nc 192.168.124.179 8080

In the server's console you will see new messages and then the server is done:

The server is configured!
Waiting for Clients to connect
A client has connected to the server!

Process finished with exit code 0

Let's debug it. We place a breakpoint after calling the accept() method and then we click on the little green bug

The server starts running

Only when a client is connected, the program reaches the breakpoint and stops

From there, we can execute the program step by step until it is finished. In this animation you can see this process

Error: Address already in use

Sometimes, after executing the server and running it again you will see a red error message on the console that says:

OSError: [Errno 98] Address already in use

This is because the port has not still been freed by the operating system. Soemetimes it takes one minute or two to free it. One solution is just to change the server port to another. For example 8081. Then running it again

Another solution is to configure the socket so that the addresses can be reused. You have to add this line below the socket creations:

# -- Step 1: create the socket
ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# -- Optional: This is for avoiding the problem of Port already in use
ls.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Reading data from the client

The accept() method returns a pair of values: the new socket used for communicating with the client and the client's ip and port values

We store the socket in the cs object (client-socket). We use the rcv() method of the cs socket for receiving the client's message and printing it on the console

# ....
# ....
# -- Waits for a client to connect
print("Waiting for Clients to connect")
(cs, client_ip_port) = ls.accept()

print("A client has connected to the server!")

# -- Read the message from the client
# -- The received message is in raw bytes
msg_raw = cs.recv(2048)

# -- We decode it for converting it
# -- into a human-redeable string
msg = msg_raw.decode()

# -- Print the received message
print(f"Message received: {msg}")

# -- Close the socket
ls.close()

Exercises

All the exercises and experiments performed during this session should be stored in the Session-10 folder

Exercise 1

  • Filename: Session-08/IPs.py

Let's play a little bit with the IP address. Try to find the IP address of your mobile phone. If you are connected to the URJC wifi you should have an IP

How to find this information depends on your mobile phone. Usually on Android phones you will find it in Settings/system/About the phone/state/IP address

Get the IP address of your computer at the LAB

Open a new file (IPs.txt) and complete the following information:

Machine Interface Date Place IP
mobile Wifi
Lab computer Wire
..... ..... ..... .......... ..............

The first column is for your computer in the lab and/or your mobile. The second is the type of interface. Wifi or wire. The third is the date. The fourth is the place: home/Alcorcon Lab and the last one is the IP address.

You should get the IP of your phone when you reach home. And also, take note of your mobile IP when you reach the LAB tomorrow. Write down all the IPs in the table

Exercise 2

  • Filename: Session-08/Ex2.txt

END of the session

The session is finished. Make sure, during this week, that everything in this list is checked!

  • You have all the items of the session 7 checked!
  • Your working repo contains the Session-08 Folder with the following files:
    • IPs.txt
    • Ex2.txt
    • Ex3.py
    • server.py
  • All the previous files have been pushed to your remote Github repo

Author

Credits

  • Alvaro del Castillo. He designed and created the original content of this subject. Thanks a lot :-)

License

Links