The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
send не успевает отправить данные до close., !*! Wazar, 31-Мрт-10, 12:24  [смотреть все]
При написании HTTP сервера столкнулся с такой проблемой.

возвращаю ответ клиенту с помощью send одним куском килобайт в 10. сразу после этого делаю close.
Клиенту доходит не вся информация. Когда использовал сниффер со стороны клиента - видел что доходин только первый пакет в 1460 байт. При этом send возвращает всю длину переданного массива то есть вроде как передал все. Если после send не делать close (делать его минут через 5) до данные гарантировано доходят, но некоторые клиенты, например Internet Explorer, ждут именно окончания соединения, и Content-Length им не указ.
Компромисный вариант - делал sleep на 1 секунду. Вроде все успевает доходить и даже чуть чуть ждет. При чем как при отправке страницы так и при отправке файла мб в 10 время ожидания примерно одиноково.

Пробовал включать/отключать блокирующий режим, пробовал использовать shutdown. не помогает.

  • send не успевает отправить данные до close., !*! anonymous, 12:34 , 31-Мрт-10 (1)
    Попробуйте говорить fsync() на дескриптор сокета.
  • send не успевает отправить данные до close., !*! svn, 16:11 , 31-Мрт-10 (2)
    Очевидно TCP стек работает не корректно. Возможно его ломает файрвол или неправильные настройки.

    >пробовал использовать shutdown. не помогает.

    Как именно пробовал? Закрывать надо на отправку.

    Вообще закрытие сокета намного сложнее, и далеко не всегда требуется, в виду наличия в http протоколе keep-alive. Как, кто и в каком случае закрывает соединение - написано в последнем RFC по http.

    • send не успевает отправить данные до close., !*! Wazar, 17:38 , 31-Мрт-10 (4)
      >>пробовал использовать shutdown. не помогает.
      >
      >Как именно пробовал? Закрывать надо на отправку.
      >
      >Вообще закрытие сокета намного сложнее, и далеко не всегда требуется, в виду
      >наличия в http протоколе keep-alive. Как, кто и в каком случае
      >закрывает соединение - написано в последнем RFC по http.

      shutdown делал и SHUT_WR и SHUT_RDWR. Не помогло. И fsync - тоже.

      На счет keep-alive - я шлю Connection: close

      >Очевидно TCP стек работает не корректно. Возможно его ломает файрвол или неправильные
      >настройки.

      Не подскажите как и что надо настроить? Кст, сервер я тестировал под 10082 портом, а на 80 порту у меня висит апач. Так вот апач все нормально шлет и даже IE все устраивает.

      • send не успевает отправить данные до close., !*! BigHo, 17:47 , 03-Апр-10 (5)
        Что за операционная система и стоит ли опция LINGER на сокете? Скорей всего это баг ОС или её настроек (посмотрите в sysctl - по поводу msl).
        • send не успевает отправить данные до close., !*! guest, 09:27 , 04-Апр-10 (6)
          >Что за операционная система и стоит ли опция LINGER на сокете? Скорей
          >всего это баг ОС или её настроек (посмотрите в sysctl -
          >по поводу msl).

          Вопрос почти в тему)
          Как ведет себя не блокируемый сокет с SO_LINGER?

          • send не успевает отправить данные до close., !*! BigHo, 09:57 , 04-Апр-10 (7)
            >>Что за операционная система и стоит ли опция 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 будет ассинхронно разрывать поток, что видимо и наблюдается в вашем случае. Вот только если дескриптор работает в блокирующем режиме, то тогда я "ой".

  • send не успевает отправить данные до close., !*! pavlinux, 03:03 , 30-Авг-10 (8)
    >При написании HTTP сервера

    Зачем?

    > столкнулся с такой проблемой.
    > возвращаю ответ клиенту с помощью send одним куском килобайт в 10.

    Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
    каким-то одним куском равна 0, хотя бы из того, что даже Jumbo frame равен 9000 байтам.


    • send не успевает отправить данные до close., !*! Volodai, 14:47 , 19-Авг-11 (9)
      > Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
      > каким-то одним куском равна 0, хотя бы из того, что даже Jumbo
      > frame равен 9000 байтам.

      Я бы сказал по другому, хотя бы потому, что всё что отправляется и имеет размер больше MTU будет некорректно отсылаться, если использовать Socket.
      Размер MTU зависит от типа сетей. Для Ethernet он равен 1500 байт +/-, для Internet и того меньше, не помню точно, можно погуглить.
      Так вот, большие пакеты нужно разбивать на куски размером меньше либо равно MTU.


      • send не успевает отправить данные до close., !*! pavlinux, 18:05 , 19-Авг-11 (10)
        >> Наивный чукоцкий программер. Вероятность того, что все 10 кило дойдут
        >> каким-то одним куском равна 0, хотя бы из того, что даже Jumbo
        >> frame равен 9000 байтам.
        >  Я бы сказал по другому, хотя бы потому, что всё что
        > отправляется и имеет размер больше MTU будет некорректно отсылаться, если использовать
        > Socket.
        > Размер MTU зависит от типа сетей. Для Ethernet он равен 1500 байт
        > +/-, для Internet и того меньше, не помню точно, можно погуглить.

        Это не наши проблемы. Нам интересен только MTU до первого маршрутизатора провайдера.

        > Так вот, большие пакеты нужно разбивать на куски размером меньше либо равно
        > MTU.

        Этим занимается ядро. Не нужно лезть ниже 7 уровня OSI при написании HTTP сервера.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру