RazGavrieli / Server_Clients_chat_in_python

This is a simple messaging app in Python3. A TCP protocol is used to transfer string messages between clients(through the server). And a UDP protocol with reliability layer on top of it is used to transfer files.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

image

Introduction

This project has been made for Computer Networking Course at Ariel University.
It is a messaging app between serval clients, through a single server.
The clients can also download files from the server, using a UDP connection with reliabilty layers ontop of it.

How to run: <<<<<<<<<<<<<<<<<<<< READ THIS <<<<<<<<<<<<<<<<<<<<<<<<

Server Side -

Download server.py and frUDP.py to the same folder on your computer.
Create a new folder within it, called "files".
run server.py through CMD or through an IDE for python.
An IP will be written in the terminal, copy it and send it to your clients.
Make sure ports 55000-55015 are open and ready to be used.
image

Client Side -

Download client.py and frUDP.py to the same folder, run client.py through CMD or an IDE for python.
A small window will pop-up, insert a working IP of a server you want to connect to and wait for the connection to be established.
image
For a linux based client side you have to install the libraries manually, install tkinter.

Implementation -

State Diagrams -

First we will acknowlage that the simple messages are sent using TCP. Which means the state diagram is fixed, and as followed:
image

My implementation of CC is in frUDP is more simple, it is also based on unique acks for each segment of the file. When the server receives nack from the client, it lowers the amount of bytes sent at each packet. When the server does not receive and ack nor nack, it lowers the amount of bytes sent at each packet. This way, the download stays stable even though the connection is not. This way we over come packet losses and latency problems.

image

When the server is initialized, it always listens to a new client.

image

Headers -

As stated in the diagrams section, the messages are sent using TCP so the header is fixed and as follows:
image

The implementation of headers in frUDP includes checksum, segment ID and data in bytes loaded into pickle (or json..)
FOR PAYLOAD (DATA IN BYTES)

32 bytes rest of bytes
checksum chuncks of 1000 bytes of data with unique segment ID for each chunk

FOR MESSAGE DATA (DATA IN STRING)

32 bytes 3 bytes rest of bytes
checksum segment ID data in bytes of the string

The managment of the two kinds of headers is easily observered in drUDP.py at lines 25-100. It is managed by the 4 functions: wrap() and unwrap() are for string data and wrap_payload() and unwrap_payload() are for data in bytes saved in a dictionary.

Establishing connection -

Inspired by TCP, I implemented three-way-handshake into frUDP. It works the same way as TCP's does, the only difference is for optimization. Information such as 'filesize' is being transffered from the server to the client using the "SYN-ACK" message.
in frUDP.py there are two functions that are responsible for establshing frUDP connection: serverside_threewayhandshake() and clientside_threewayhandshake(). At first, the client sends the server a "SYN" message and waits for reply. Once the server receives the message it sends a "SYN-ACK" message, that is followed by 'filesize' which is the amount of bytes the server is intending to send to the client. The client receives the message and sends a final "ACK" message before the file tranfer initializes.
image

initial construction idea:

For the server there is a main thread that runs in a while true loop, and listens for new connections.
each connection receives 2 threads; one for listening and one for sending.
On the client it is simillar, once connection has been established 2 threads are being ran; one for lisetning and one for sending.
Once the client asks for a file, a new thread is initialized for the function "get_file" so the TCP connection is still running in the background.
On the server side, once a client asks for a file, two threads are being initialized, one for sending the file itself and one for listening for acks\nacks\ack-all.
.

Documentation of expermients:

On the client side in lines 75-85 I've implemented "fake packet loss simulation", where we can create packet loss and send nacks messages (or even not send nacks or acks for a specific packet).
Using this method, we could observe our changes in download speeds according to packet losses. (Congestion Control).
one of the most difficult things in this project was figuring out the values for changes in download speed at each nack or latency recognition
The following image shows the part of the code where you can create packet loss, send nacks or not send anything back to the server (as if the packet didn't arrive)
image


The part of the code that controls the transfer speeds (in server.py lines)

keep in mind that values[1] represents the amount of bytes (in thousands) that will be sent at a time.

        if data[:4] == "NACK":
            if values[1]>8:
                values[1]-=3
        ...
        
        ...
        elif data[:3] == "ACK":
            list = eval(data[3:])
            if values[1]<60:       
                values[1]+=1 

The raw data for the following charts is in google sheets:
https://docs.google.com/spreadsheets/d/1wk7WyMW9k_cAbM6wEbKLBgx3a4vXbHEUQjmjdHLtLuA/edit?usp=sharing

Example of 0% packet loss file transfer speeds

image

Example of 5% packet loss file transfer speeds

image

Example of 10% packet loss file transfer speeds

image

wireshark snapshot of a file transfer, the pcap file is included for more information

image

Example of 10% packet loss file transfer speeds, with a pause after 50% (initiates slow-start), the wireshark snapshot included is of this transfer

image

Comparsion between 20% and 30% loss, with average

image

About

This is a simple messaging app in Python3. A TCP protocol is used to transfer string messages between clients(through the server). And a UDP protocol with reliability layer on top of it is used to transfer files.


Languages

Language:Python 100.0%