Мне интересно, как libevent запускает обратный вызов. Например, предположим, что клиент повторно отправляет 4-байтовое сообщение. На стороне сервера, кажется, не каждая 4-байтовая передача вызовет обратный вызов чтения. Например, я обнаружил, что обратный вызов иногда запускается в точке получения 8-байтового сообщения (или другого номера). Можно ли настроить libevent таким образом, чтобы обратный вызов чтения на стороне сервера запускался для каждого 4-байтового сообщения, отправленного с клиента?Как libevent вызывает обратный вызов
ответ
Я считаю, что ваша проблема касается отправки, а не о получении. Libevent, вероятно, не отправляет ваши данные немедленно из-за вывод буферизации, при этом ваш обратный вызов read
вызывается только тогда, когда клиент действительно получает данные, которые вы отправили.
См. Nagle's algorithm (aka TCP_NODELAY
). Затем попробуйте отключить его, чтобы увидеть, если это действительно так:
int flag = 1;
int ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
Можно ли настроить Libevent такое, что чтение обратного вызова на стороне сервера срабатывает для каждого сообщения 4 байт, посланного от клиента?
Не совсем. Вы можете получать несколько сообщений «одновременно», поскольку TCP является потоковым протоколом. Единственное, что касается вашего приложения, это знать, где начинается и заканчивается каждое сообщение.
Игнорирование Libevent с целью объяснения, вы обычно:
- Keep вызова
recv
в цикле; - Добавить полученные данные/полезную нагрузку в буфер;
- Вызвать метод обработки этого буфера;
- Метод процесса проверяет размер буфера, чтобы узнать, содержит ли он как минимум 1 сообщение. В вашем случае вы хотите, чтобы оно составляло не менее 4 байтов, поэтому вы знаете, что у вас есть как минимум 1 полное сообщение для обработки. Если ваш буфер имеет размер, который не кратен 4 байтам (что никогда не должно происходить при очень малом размере вашей полезной нагрузки), скажем, 10 байт, вы обрабатываете начальные 4 байта, удаляете их из буфера, повторяете еще раз и затем сохраните оставшиеся 2 байта в буфере.
Я вижу. Возможно ли, чтобы сервер получил сообщение с размером не кратным 4? – Jes
Помните, что ваша полезная нагрузка составляет ровно 4 байта, тогда ответ НЕТ, но, конечно, я не рекомендую полагаться на это. Вам лучше использовать механизм для хранения полученных данных (см. [Bufferevent's] (http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html)), а затем обработать его. Если вы обнаружите, что не получили полного сообщения, вы должны просто ждать большего. – jweyrich
Спасибо! Это имеет смысл. – Jes