Почему нам нужно читать() перед записью() в программе TCP-сервера?

Насколько я понимаю, простой TCP-сервер будет закодирован следующим образом.

socket() - bind() - listen() - accept() - read() - write()

Клиенты будут написаны следующим образом.

socket() - bind() (необязательно) - connect() - write() - read()

Обратите внимание на разницу в порядке вызовов read() и write() между клиентской и серверной программой.

Требуется ли всегда читать () перед записью () в серверной программе, и если, то почему?

Спасибо, Нага


person Naga    schedule 20.03.2010    source источник


Ответы (4)


Это не обязательно, но серверу имеет смысл прочитать запрос перед написанием ответа. Обратите внимание, что чтение с обеих сторон необходимо достаточно часто, чтобы предотвратить распределенную взаимоблокировку: например, если обе стороны пытаются записывать и не читают, тогда промежуточные буферы будут заполнены, и ни одна из сторон не сможет выполнить запись. продолжить. Одним из решений для этого является наличие отдельного потока, который продолжает читать, если есть что читать (это относится как к клиенту, так и к серверу).

person abc    schedule 20.03.2010

Простой ответ - нет. Вы вольны делать все, что вам нравится.

Однако я быстро оговорюсь, поскольку большинство протоколов рассчитаны на ожидание отправки клиентом чего-либо. В конце концов, сервер по своей природе обслуживает запросы и должен ждать, чтобы узнать, что это за запрос, будь то «GET /» или «HELO» или что-то еще. Таким образом, вполне естественно, что сервер читает перед отправкой какого-либо ответа клиенту.

Тем не менее, вы могли бы, если бы вам хотелось, чтобы информация о версии передавалась клиенту до того, как вы что-либо читали. Чтобы увидеть эффект, подключитесь к своему серверу с помощью telnet.

person Community    schedule 20.03.2010
comment
На самом деле существует множество протоколов, в которых сервер отправляет баннер или приветственное сообщение сразу после подключения клиента - на ум приходят SSH, SMTP, POP3 и IMAP. - person caf; 22.03.2010

Вы можете выполнять их в любом порядке. Однако сервер обычно генерирует ответ из операции read(), а затем записывает его с помощью операции write(), так что такой порядок имеет смысл.

Если вы работаете с несколькими клиентами, вы должны использовать мультиплексор, например select, чтобы уведомлять вас, когда у клиентов есть данные, готовые для чтения, чтобы ваш сервер не блокировался каждый раз, когда вы пытаетесь прочитать () от клиента, который не отправил что угодно.

person lunixbochs    schedule 20.03.2010

Это не обязательно, серверная программа может писать в сокет без предварительного чтения. Но во многих случаях серверная программа должна знать, чего хочет клиент, поэтому она сначала вызывает read().

person Bohdan    schedule 20.03.2010