Здравствуйте, у меня два компьютера соединенные коммутатором. На одном запущена программа-сервер(А), на другом программа-клиент(Б). Между ними средствами сокетов беркли реализован протокол передачи данных такой: читаем первые четыре байта в них заложена длина сообщения(х) в байтах, получаем длину сообщения х+4, далее чтоб записать сообщение заполняем первые 4 байта значением оставшейся длины, записываем. Размеры буферов приема-передачи имеют фиксированный размер(для простоты, максимальный размер сообщения не больше чем размер буфера). Дак вот сначала, и А и В были на одном компе. и через них туда-обратно гонялось по петле по 16 гигов(не всегда программы завершались, иногда блокировались) а как вынес сервер на другой комп. (симулируя реальную сеть), стало приходить-уходить гораздо меньше данных, далее сервер на epoll_wait() ,блокировался. Кстати, сокеты блокируемые, это связано с простотой кода-главное следить за количеством передаваемой информации и все будет хорошо, по крайней мере раньше так думал).
Да, много написал) Но уже битую неделю ищу решение проблемы, а именно: "Что за хрень? через блокируемые сокеты передается известное обоим сторонам количество данных". Но они блокируются то на epoll_wait(), то на read/write, то программа полностью выполняется. Не ожидал я такого поведения, до этого работал с не блокируемыми сокетами с EPOLL (ET), все летало. Сейчас думается может добавить-изменить опции сокетов как на SOL_SOCKET ,так и на IPPROTO_TCP уровнях. Что скажете-посоветуете?
Да, еще добавлю: в некоторых запросах клиента если например в первых 4 байтах содержится -1, сервер не должен отвечать клиенту, вот после таких "однонаправленных" итераций чаще всего глохнет.
Походу придется писать дополнения под циферками:
1) Немного начинаю понимать. Написал прототип программ с искусственными размерами посылаемых сообщений чтоб точно знать где сколько должно прийти-уйти. Алгоритм состоит из 8 итераций, в первой, второй и третьей клиент шлет сообщения только по 4 байта со значением -1, сервет читает -1 при таком значении он не должен отвечать, клиент об этом знает, далее он шлет максимальный размер буфера, сервер читает и отдает также максимальный размер буфера, а далее нет и смысла объяснять) Просто первые три запроса запихались в буфер ядра и отослались серверу целиком, а сервер воспринял как один запрос. Далее пошел полный шлак. Так что не вижу другого выхода, придется читать, кусками сначала константный размер с длиной а потом уже все остальное( А можно по другому?
Почитать учебник Снейдера по TCP/IP.
В частности, то место, где написано, что read (write) может считать меньше байт, чем у нее указано в качестве параметра.
Да я слышал о такой особенности, если "a"=значение первых 4-x, прочитаных байт а "b"-максимальный размер буфера при условии что a<=b; можно вот так "char flags=0;int r, tr=0,a,b=MAX_LEN_BUF;a=b;do{r=read(sd,&mass[tr],a-tr);if(r<=0){закрытие сокета}tr+=r;if(tr>=4 && flags==0){читаем длину;присваиваем это значение a; flags=1;}}while(tr
jcmvbkbc, о, на одном оксидосерном сайте на меня недавно набросились, подробно расписывая, что write всегда пишет столько, сколько указано, или блокирует поток.
Данил Тунев, не видя ваш код сложно что-то сказать. Самая распространенная ошибка - отсутствие проверок того, что выдают системные вызовы. Если вы все же удосужитесь почитать учебник, вы там найдете и способ за один системный вызов передать кучу буферов ("запись со сбором") и тактический прием правильного разбора заголовков пакета.
Фокс Йовович, Если бы не следил за возвращаемыми значениями read/write, было бы вообще плохо) Ну да, есть смысл принять максимальное сообщение а потом уже разложить всю логику по полочкам, заманчиво, подумаю)
Фокс Йовович, Тут подумал, конечно вам огромное спасибо, верное решение! но недоверие у меня к книгам зашкаливает, почитал в свое время "воздушных" книг. В принципе, манов достаточно. Код не выложу, по той причине что его много! и не в одном файле, а еще, не хочу чтоб его кто то знал) В вопросе все было понятно