Впервые я пытаюсь реализовать некоторый сетевой протокол через TCP/IP. Я разработал один, но я не уверен, насколько он эффективен.Каковы наилучшие методы проектирования и реализации сетевых протоколов?
Дизайн
Так вот моя идея: после того, как клиент открывает TCP/IP соединение с сервером, каждый раз, когда он хочет сделать запрос, в первую очередь он посылает размер запроса, затем какой-то символ-разделитель (новый строка или пробел), и после этого фактический запрос (тот же самый главный используется в HTTP, и я думаю, что в большинстве случаев эта идея используется).
Например, если клиент хочет отправить GET ASD, он фактически отправит 7 GET ASD (при условии, что пространство является разделителем).
Для сервера, для каждого клиентского сервера есть буфер, в котором он сохраняет входящие запросы. Всякий раз, когда он получает некоторый новый фрагмент символов от клиента, сервер добавляет его в соответствующий клиентский буфер. После этого сервер попытается получить длину содержимого запроса (в этом примере 7) и проверяет, больше ли его длина или длина. Если это так, сервер получает фактическое содержимое запроса, обрабатывает и удаляет его из буфера.
Реализация
Это все было о дизайне протокола, в настоящее время некоторые замечания о фактической реализации: Я думаю, что основная проблема здесь эффективного осуществления и управления буферами.
Я думаю, что буфер с размером 2 * MAX_SIZE_OF_ONE_REQUEST будет достаточным для обслуживания одного клиента, потому что куски, полученные сервером, могут одновременно содержать конец первого запроса и начало второго. Это мое предположение, если я ошибаюсь, и нам нужно больше или меньше места, пожалуйста, дайте мне знать, почему.
Я думаю, что есть два способа хранения запросов в буфере, пока они не служили:
Всякий раз, когда сервер получает новый кусок символов, сервер добавит его к правой стороне буфера. Как только буфер будет содержать полный запрос, сервер будет обрабатывать его и перемещать влево весь остальной буфер в начале буферного пространства.
Некоторые циклические буфера, которые не перемещают буфер в начале после запроса обработки.
Это мои мысли о реализации буферов с асинхронным I/O в виде (сервер будет использовать Epoll/Kqueue/выберите для получения запросов от клиентов). Я думаю, что если сервер не будет использовать асинхронный ввод-вывод для связи с клиентами, то реализация буфера будет намного проще.
Также я не решил, как сервер должен вести себя, когда он получает неверный запрос. Должна ли она закрывать связь с клиентом?
Возможно, я написал много, но меня действительно интересует эта тема и вы хотите узнать как можно больше. Я думаю, что таких меня много, поэтому любые проблемы с реальным миром в отношении этой темы и лучших практик для их решения будут очень полезными.1.
Требования к API важны для анализа перед выполнением любого вида дизайна. Если вы можете подробно остановиться на них, это может быть проще. –
Я был очень воодушевлен Редисом и для цели обучения Я начал небольшой проект Kivi (K/V Store): http://github.com/giolekva/kivi Итак, такие команды, как GET, SET, DEL, INCR, ... как в Redis. – giolekva
(Комментируя, потому что у меня нет полного ответа на ваш вопрос): Я обнаружил, что лучше предотвратить возможность искаженных запросов. В этом случае длина и запрос могут быть непоследовательными, поэтому я бы покончил с длиной. Вместо этого у вас может быть какой-то специальный терминатор ('' \ 0'' хорошо работает во многих случаях).Конечно, по-прежнему существует вероятность того, что клиент отправит бесконечную строку для перегрузки сервера, но по крайней мере вы не будете висели, ожидая большего количества байтов, если длина была неправильной. – Jonathan