CSE 40771 - Distributed Systems

CSE 40771 - Distributed Systems - Spring 2026

View the Project on GitHub

A6 - Concurrency/P2P

Overview

To realize our final P2P file distribution system we must be able to support more than a single client and server pair. To get closer to the BitTorrent implementation our peer also must support requests from other peers to share data we have, while simultaneously downloading the data we need.

In this assignment we will implement this capability and finally have our first P2P communication (it’s about time!).

Event Driven Server

In class, we discussed several models for building servers: single-threaded (what you have already), multi-threaded, multi-process, and event-driven. We are going to use the latter model, because all operations must share the same underlying checkpoint and transaction log.

Here is how to think about it:

Your server will keep track of the master socket on which it is listening for new connections. It will also have a dictionary of sockets, each one representing a currently-connected client. In the server’s main loop, it should use epoll to determine which socket is readable.

If our peer’s only job was to perform the server functionality we could block until some event happens. However our peer needs to be working on getting the data itself while also serving other peers. Thus we need to poll the server socket for activity, handle the request, and return to our work.

If we find the master socket is ready for reading, then the server should accept a new connection and add it to the set. If any other socket is ready for reading, then the server should read a request from the socket, perform the action, send a response, and return to its polling loop.

This approach strikes a balance between concurrency and complexity. The server can handle multiple clients connected at once, and can interleave multiple requests to satisfy all comers. Each request still executes one at a time, so we say that the request stream is serialized. You won’t get the performance benefit of running multiple processes/threads concurrently, but you won’t have the synchronization problems from that either.

Be sure to test your server carefully before moving on. Try various combinations of clients connecting and leaving, and ensure that the server does not crash, no matter when or how the clients connect and disconnect. Add some debugging output to assure yourself that the server is in fact interleaving requests from multiple clients.

Peer Consolidation

At this point we are going to combine the client and server into the Peer, such that every member of the system is an instance of Peer. Begin by making a main program called Peer.py that does the following:

Required Functionality

For this assignment your solution should meet these requirements:

Recap and Overall Difference

The above requirements describe an interesting system. It is not far from the one we have been working with.

Previously, we started a dedicated server, then connected with a client. Subsequent clients would connect to the same dedicated server.

Now every process is a peer who contains a server. Subsequent peers may connect to any peer that was already running when it starts.

The reason for this requirement is to prevent the potential for deadlock which would otherwise occur if any two peers were able to initiate a connection with each other.

Testing and Measurement

Basic Function

Evaluate your system in the presence of multiple peers as follows:

python Peer.py project_name peer_name
python Peer.py project_name peer_name_1 & \
python Peer.py project_name peer_name_2 

System Analysis

Perform the same test as before but in several stages. Start 1 peer, then 2, then 4. Create a diagram (text, plot, drawing) of the system and what occurred when it was running.

What to Turn In

Please review the general instructions for submitting assignments.

Turn in all of your source code, along with a lab report titled REPORT that describes the following in detail: