При написании HTTP сервера столкнулся с такой проблемой.возвращаю ответ клиенту с помощью send одним куском килобайт в 10. сразу после этого делаю close.
Клиенту доходит не вся информация. Когда использовал сниффер со стороны клиента - видел что доходин только первый пакет в 1460 байт. При этом send возвращает всю длину переданного массива то есть вроде как передал все. Если после send не делать close (делать его минут через 5) до данные гарантировано доходят, но некоторые клиенты, например Internet Explorer, ждут именно окончания соединения, и Content-Length им не указ.
Компромисный вариант - делал sleep на 1 секунду. Вроде все успевает доходить и даже чуть чуть ждет. При чем как при отправке страницы так и при отправке файла мб в 10 время ожидания примерно одиноково.Пробовал включать/отключать блокирующий режим, пробовал использовать shutdown. не помогает.
Попробуйте говорить fsync() на дескриптор сокета.
>Попробуйте говорить fsync() на дескриптор сокета.Глупость. Сокет это не файл, сокеты не кешируются, и запись в них не откладывается.
Очевидно TCP стек работает не корректно. Возможно его ломает файрвол или неправильные настройки.>пробовал использовать shutdown. не помогает.
Как именно пробовал? Закрывать надо на отправку.
Вообще закрытие сокета намного сложнее, и далеко не всегда требуется, в виду наличия в http протоколе keep-alive. Как, кто и в каком случае закрывает соединение - написано в последнем RFC по http.
>>пробовал использовать shutdown. не помогает.
>
>Как именно пробовал? Закрывать надо на отправку.
>
>Вообще закрытие сокета намного сложнее, и далеко не всегда требуется, в виду
>наличия в http протоколе keep-alive. Как, кто и в каком случае
>закрывает соединение - написано в последнем RFC по http.shutdown делал и SHUT_WR и SHUT_RDWR. Не помогло. И fsync - тоже.
На счет keep-alive - я шлю Connection: close
>Очевидно TCP стек работает не корректно. Возможно его ломает файрвол или неправильные
>настройки.Не подскажите как и что надо настроить? Кст, сервер я тестировал под 10082 портом, а на 80 порту у меня висит апач. Так вот апач все нормально шлет и даже IE все устраивает.
Что за операционная система и стоит ли опция LINGER на сокете? Скорей всего это баг ОС или её настроек (посмотрите в sysctl - по поводу msl).
>Что за операционная система и стоит ли опция LINGER на сокете? Скорей
>всего это баг ОС или её настроек (посмотрите в sysctl -
>по поводу msl).Вопрос почти в тему)
Как ведет себя не блокируемый сокет с SO_LINGER?
>>Что за операционная система и стоит ли опция LINGER на сокете? Скорей
>>всего это баг ОС или её настроек (посмотрите в sysctl -
>>по поводу msl).
>
>Вопрос почти в тему)
>Как ведет себя не блокируемый сокет с SO_LINGER?Из мана на setsockopt:
SO_LINGER controls the action taken when unsent messages are queued on
socket and a close(2) is performed. If the socket promises reliable
delivery of data and SO_LINGER is set, the system will block the process
on the close(2) attempt until it is able to transmit the data or until it
decides it is unable to deliver the information (a timeout period, termed
the linger interval, is specified in seconds in the setsockopt() system
call when SO_LINGER is requested). If SO_LINGER is disabled and a
close(2) is issued, the system will process the close in a manner that
allows the process to continue as quickly as possible.Если вкраце - то он как раз задерживает выполнение close до тех пор, пока все данные не будут отправлены. Вот только я его не разу не использовал, и все нормально работа(ет,ло). Только в одном случае я его бы использовал - при неблокирующем вводе/выводе. Потому как send в этом случае действительно возвращает размер буфера передаваемого буфера авансом, и последующий close будет ассинхронно разрывать поток, что видимо и наблюдается в вашем случае. Вот только если дескриптор работает в блокирующем режиме, то тогда я "ой".
>При написании HTTP сервераЗачем?
> столкнулся с такой проблемой.
> возвращаю ответ клиенту с помощью send одним куском килобайт в 10.Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
каким-то одним куском равна 0, хотя бы из того, что даже Jumbo frame равен 9000 байтам.
> Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
> каким-то одним куском равна 0, хотя бы из того, что даже Jumbo
> frame равен 9000 байтам.Я бы сказал по другому, хотя бы потому, что всё что отправляется и имеет размер больше MTU будет некорректно отсылаться, если использовать Socket.
Размер MTU зависит от типа сетей. Для Ethernet он равен 1500 байт +/-, для Internet и того меньше, не помню точно, можно погуглить.
Так вот, большие пакеты нужно разбивать на куски размером меньше либо равно MTU.
>> Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
>> каким-то одним куском равна 0, хотя бы из того, что даже Jumbo
>> frame равен 9000 байтам.
> Я бы сказал по другому, хотя бы потому, что всё что
> отправляется и имеет размер больше MTU будет некорректно отсылаться, если использовать
> Socket.
> Размер MTU зависит от типа сетей. Для Ethernet он равен 1500 байт
> +/-, для Internet и того меньше, не помню точно, можно погуглить.Это не наши проблемы. Нам интересен только MTU до первого маршрутизатора провайдера.
> Так вот, большие пакеты нужно разбивать на куски размером меньше либо равно
> MTU.Этим занимается ядро. Не нужно лезть ниже 7 уровня OSI при написании HTTP сервера.