Q: Синхронизация сервера и клиента по протоколу TCP Имеется сервер, организованный с помощью TcpListener, и клиент, организованный с помощью TcpClient. Данных от клиента серверу пересылается много, поэтому делается это построчно. Дело в том, что при пересылке сообщения от клиента к серверу последнему нужно некоторое время для обработки данных (вставляет данные из полученного сообщения в БД). Если поставить какой-нибудь примитивный Thread.Sleep(1000) перед каждым отправлением данных, то тогда сервер успевает за клиентом, но этот метод мне крайне не нравится. Как заставить их синхронизироваться друг с другом?

A: *

*Клиент посылает серверу пакет с сообщением. (используйте преимущественно json)

*Сервер в lock() добавляет добавляет сообщение в ConcurrentDictionary<long, string>, но проверяя long на уникальность для Dictionary, long берётся на основе DateTime.Now.Ticks на стороне сервера, если long не уникален - делается long++ пока не станет уникальным.

*Сервер сразу отвечает клиенту что long принят и встал в очередь на обработку.

*Клиент принимает long и заводит его в List<long> ожидающий подтверждения записи на стороне сервера.

*Клиент в цикле по таймеру запрашивает у сервера List<long> ожидающих подтверждения записи.

*Сервер так-же крутит в цикле свой ConcurrentDictionary<long, string> и если Dictionary не пустой - берёт сообщения и отправляет на запись в БД. Записанные сообщения удаляет из Dictionary.

*Сервер при получении List<long> (пусть будет буфером) сверяет его с ConcurrentDictionary<long, string> внутри lock() и если в Dictionary нет long - удаляет его из List<long> буфера.

*Сервер отвечает отфильтрованным List<long>, в котором будут содержаться только те long, которые ещё не были записаны в БД.

*Клиент сравнивает исходный отправленный List<long> (не текущий, т.к. могли появиться ещё сообщения) и полученный List<long> от сервера (внимание List<long> должен быть пустой, а не null), после чего клиент удаляет записанные в БД long идентификаторы сообщений из текущего List<long>.

Это пример примитивной клиент-серверной архитектуры.
Достоинства:

*

*Придумана за 15 минут

*Примитивный

*Можно развивать!!! (в любом направлении)

*Можно очень просто сделать разные типы сообщений, не только текстовая строка

*Никто никого не ждёт (клиент не ждёт пока сервер запишет сообщение в БД)

*Есть система подтверждений о записи в БД (синхронизация, условно можно рисовать галочки как в Телеграм)

*Можно изменять принципы синхронизации как душе угодно, например выбросить List<long> и сделать что-то более надёжное и осмысленное, и так-же заменить Dictionary<long, string> на какой-нибудь более полноценный Dictionary<id_struct, ICustomMessage>

*Быстрая синхронизация, запрашивать можно хоть каждую 1/100 секунды, если ожидающих запись в БД сообщений не очень много

*Поддержка многопоточности на уровне концепта (вся работа с сервером может быть в отдельном потоке или по таймерам, ничего не сломается, но не нужно забывать что интерфейс клиента всегда должен обновляться через Invoke(), если у вас GUI на формах)

Недостатки:

*

*Придумана за 15 минут

*Забагованный (по любому есть косяки, например клиент пометит что сообщение записано в БД если сервер перезагрузится, это нужно лучше продумывать и вместо List<long> использовать какой-нибудь более надёжный подход)

*Требует продуманной системы сообщений (построчно писать не получится, хотя тем-же json'ом можно и в одну строку, но лучше так не делать)

