Szybko mnie przejrzałeś.
8 lat dydaktyki robi swoje...
Co do 3 pytania
Pytanie 3 było na przypadek komercji.

Praca zaliczeniowa ma kilka miłych cech:
* Możesz sobie pozwolić na skalowanie projektu na kilkudziesięciu/góra kilkuset użytkowników.
* Nie musisz zapewniać SLA dla klientów
* Ochrona przed złośliwymi użytkownikami/DoS/DDoS jest sprawą drugorzędną.
* Nie musisz się chrzanić z RODO/GDPR
Z językiem bym się bardzo zastanawiał nad tym C++. Naprawdę mało rozwiązań tego typu jest w nim pisane. Z kompilowanych języków najwięcej rzeczy "z pudełka" do takiego projektu daje Go, potem Rust. Go ma całą kryptografię, TLS-y, kompresję, serwery HTTPS w bibliotece standardowej.
Masz dwie główne topologie:
*
Klient-Serwer (gwiazda, tryb store-and-forward z centralnym serwerem/serwerami, tak działa 99,9% komunikatorów)
Możesz popatrzeć na gotowe rozwiązania kolejek komunikatów (MQTT, AMQT). Jak pomyślę, serwer Mosquitto ma 95% potrzebnej funkcjonalności serwerowej zaimplementowanej bezpośrednio - pozostałe 5% załatwiłby mikroserwis przypięty z boku, zajmujący się managmentem i buchalterią. Genialną cechą Mosquitto jest to, że może tworzyć dynamicznych użytkowników na podstawie DN certyfikatu SSL i można robić dynamiczne ACL-ki do kolejek na bazie nazwy użytkownika. Klientów MQTT masz do każdego popularnego języka (także dla JS, więc klienta możesz zrobić czysto przeglądarkowego i C++, jak promotor się uprze).
*
P2P (brak centralnego serwera)
P2P ma kilka dodatkowych utrudnień:
* trzeba rozwiązać problem dostarczenia wiadomości, gdy czasy pracy nadawcy i odbiorcy nie przecinają się (już to zauważyłeś, dobrze). Rozwiązaniem jest rozrzucenie komunikatu do kilku innych klientów - może któryś będzie działał jak pojawi się odbiorca. Odbiorca potem rozsyła potwierdzenie odbioru, który globalnie wipuje tą wiadomość z sieci. Warto dodać TTL, żeby nie zaśmiecać sieci, jak jakiś odbiorca się wypisze z sieci permanentnie.
* P2P nie lubi mechanizmu NAT (brak NAT możesz przyjąć w założeniach pracy - jak prom się zgodzi. Jak nie, to potrzebujesz jakiegoś dodatkowego serwera np z protokołem STUN/TURN)
Jeżeli chodzi o sam transport danych między klientami, popatrz na bibliotekę
libP2P. Daje ci ona bardzo dużo fajnych mechanizmów ułatwiających komunikację P2P (w tym NAT-traversal). Nad tym można zbudować bardzo ciekawy komunikator pracujący bez serwera centralnego. Dodatkowym mykiem jest to, że jest implementacja lipP2P w JS - może działać całkowicie w przeglądarce.
Niezależnie od topologii - jak chodzi o zabezpieczanie samych wiadomości (kryptografia end-to-end), popatrz na protokół OTR (używane np w Jabberze) oraz na implementację w kliencie Signala (mechanizm double-ratchet)