Reminder:

The several solutions to handle concurrency

As soon as you create a networked application, your application (process) need to handle concurrent things: it can for example be sending something but at the same time receiving something (from one or more remote processes).

Indeed, for example, reading from a socket can be a blocking operation (the program will freeze when reading and no data is send from the other side). That is why this operation is often done by a dedicated sub-program that needs to run concurrently with the rest of the program.

There are several ways to handle this concurrency in your application. We discuss some of them below.

The recommended solutions for beginners are prefixed with (((RRR)))

Using threads or the equivalent

A first kind of concurrency approaches is to use several threads (lightweight, parallel execution points in your program). For instance, there could be a thread for each socket (to wait for data arriving on this socket) + one thread for each server socket (to wait for new connections) + some other threads for the application logic.

This proliferation of parallel execution threads makes it necessary to restrict the access to some data structure that are not thread-safe (a data structure is thread-safe if it can be accessed by several threads in parallel, which is rare).

Creating a thread can be done easily in Java (https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html) or in Python (https://docs.python.org/3.7/library/threading.html#thread-objects), and also in most other languages.

    ...
    public static main(String[] args) {
       // Starting a Thread in Java
       Thread t = createMyThread();
       t.start();
    }
    
    private static Thread createMyThread() {
        return new Thread(() -> {
            try {
                // do some stuff, maybe a loop
            } catch (InterruptedException ex) {
                // ....
            }
        });
    }
# Starting a Thread in Python
from threading import Thread
def create_my_thread():
    def do_some_stuff():
        # do some stuff, maybe a loop

    t = Thread(target=do_some_stuff)
    return t

if __name__== "__main__":
    t = create_my_thread()
    t.start()

In Java, one can easily prevent two threads from simultaneously accessing an object by using the synchronized keyword (see https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html). This solution might easily end up in deadlocks and is not recommended for the project.

(((RRR))) Using threads and some BlockingQueues / queues

See above about threads and see “practical-1” examples.

(((RRR))) Using select

The idea in this approach is to have a single thread (so a traditional non-concurrent application) that will use the select API to ask the system for a list of all sockets that have available data.

The recommended reading to undestand this approach (for both Python and Java) is the Python documentation (https://docs.python.org/3/howto/sockets.html#socket-howto). Additionaly, a quick tutorial with the Java NIO (new IO) API (https://www.baeldung.com/java-nio-selector).

Concurrency in the Rust language

Rust is a language designed to make memory management safer and as such handles threading differently.

One can find a 2015 example of socket programming in Rust (https://nbaksalyar.github.io/2015/07/10/writing-chat-in-rust.html), and some networking library in the “low-level” section of (https://github.com/rust-unofficial/awesome-rust#network-programming).

Using async/await language features

This approach is somewhat similar having multiple threads, but these are “coroutines” (microthread) and will execute one by one, without actual parallelism but still with the possibility to do blocking calls (like reading from a socket).

The async/await features need both language support and library support. It is progressively appearing in most languages these years, see for example in Python (https://docs.python.org/3/library/asyncio.html) or Javascript (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) or Java (java.util.concurrent and the https://github.com/electronicarts/ea-async compiler plugin).

Using an actor model

This approach is very similar to using threads and some BlockingQueues. Some framework make it possible to create actors: an actor is like a thread, that executes some loop and reacts to some messages sent by other actors (inside your application). The messages are temporarily stored in an “inbox”, each actor (and thus thread) having its own inbox. As such the inbox is nothing more than the equivalent of a BlockingQueue.

(untested) some actor frameworks: