На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
    > Зависает отправка данных WSASend
      использую блокирующие сокеты в клиенте и IOCP на сервере и клиент и сервер в локальной сетке.

      создание сокета:
      ExpandedWrap disabled
            ZeroMemory(&hints, sizeof(hints));
            hints.ai_family     = AF_UNSPEC;
            hints.ai_socktype   = SOCK_STREAM;
            hints.ai_protocol   = IPPROTO_TCP;
         
            m_socket = WSASocket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, 0);

      отправка данных на стороне клиента:
      ExpandedWrap disabled
            WSABUF dataBuf;
            dataBuf.len = bytesToSend;
            dataBuf.buf = (CHAR*)mSendBuffer;
         
            int rc = WSASend( m_socket, &dataBuf, 1, &sendBytes, 0, NULL, NULL );


      размер каждого пакета 2072 байта
      клиент шлет данные непрерывно.

      По логике вещей если сокет блокирующий то WSASend вернет значение или если ошибка в сокете или данные реально отправлены.
      В итоге у меня WSASend наглухо виснет ровно на 70м блоке данных

      Счетчик принятых пакетов на сервере показывает три принятых. :wall:

      Если после WSASend поставить Sleep( 100 ) то все идеально работает.
      раскурить где собако порылась не получается.
      нужен хелп
        progman
        WireShark'ом смотрел, какие пакеты посылаются и доходят ли они?
          progman
          Ты по факту завалил датой тот буфер памяти, отведенный для сокета;

          Добавлено
          работает FlowControl
            Странное семейство адресов. <_<
            Цитата progman @
            hints.ai_family = AF_UNSPEC;

            Все дальнейшее:
            Цитата progman @
            hints.ai_socktype = SOCK_STREAM;
            hints.ai_protocol = IPPROTO_TCP;

            просто вопиет о семействе AF_INET.

            Цитата progman @
            размер каждого пакета 2072 байта
            клиент шлет данные непрерывно.
            В итоге у меня WSASend наглухо виснет ровно на 70м блоке данных
            Счетчик принятых пакетов на сервере показывает три принятых. :wall:
            Если после WSASend поставить Sleep( 100 ) то все идеально работает.
            раскурить где собако порылась не получается.

            Шлет данные непрерывно - это в цикле что ли?
            Ну и самое главное на мой взгляд.
            Собака порылась в размере буфера отправки сокета клиента.
            Модуль TCP просто не успевает отослать все из буфера - или в сети затор, или коллизия, или в карточке буфер забит или просто еще чего - ну не успел просто. Такие ситуации встречаются сплошь и рядом.
            Потому слип и решает все проблемы.
            Значит или надо поиграть размером буфера отправки SO_SNDBUF - а он по умолчанию очень небольшой, или придерживать отправу на пару сотен милисекунд.

            Добавлено
            Цитата nemez @
            Ты по факту завалил датой тот буфер памяти, отведенный для сокета;

            Ну во,пока я тут расписывался, ответ уже пришел,блин :D
              разобрался.
              Слишком большой блок данных шлю для тестов и не учел что CP может не принять его полностью за один вызов WSARecv
              в реальном сервере больше 16 байт в блоке не бывает а я 4 кило пуляю )
              В общем сбилась система чтения размера следующего блока - чтение самого блока и подвисло все.
                Честно говоря, мало что понял :( Виснет то send()на клиенте. А он к серверу никаким боком. Или и на сервере были проблемы?
                Впрочем уже не суть.
                Работает. :yes:
                  Цитата Oleg2004 @
                  Честно говоря, мало что понял :( Виснет то send()на клиенте. А он к серверу никаким боком. Или и на сервере были проблемы?
                  Впрочем уже не суть.
                  Работает. :yes:

                  У меня сначала шлется 4 байта размер блока потом сам блок
                  На одном из блоков вместо 2048 байт тела блока было прочитано только 1456 - я этот нюанс не учел и считал что блок прочитан полностью и следующие 4 байта в потоке это размер уже следующего блока.
                  А так как клиент слал массивы по 2048 байт забитые нулями, то в итоге сервер после 1456го байта прочитал 4 нуля как размер следующего блока на приемку и стал бесконечно читать из потока по 0 байт
                  А тестовый клиент не мог отправить данных больше чем размер буфера ну и вставал колом в ожидании когда сервак разгребет наваленные данные..
                    Ну теперь более менее понятно. Сервер не может отослать АСК на клиент, и клиент вис.
                    Ну а все таки как насчет AF_UNSPEC? :)
                    к чему такой изврат?
                      progman
                      так должно быть ибо такая архитектура систем.
                      Он не стал колом, а стал ждать когда твой клиент соизволит от сервера забрать данные.
                      У тебя еще есть один серьезный прокол по теме - тебе нужно в цикле, отправлять данные пока они не будут отправлены все.
                      ExpandedWrap disabled
                        int rc = WSASend( m_socket, &dataBuf, 1, &sendBytes, 0, NULL, NULL );

                      не покатит, rc - по факту количество байт или sendBytes - количество байт, реально отправленных твоим сендом.
                      Т.е. ты можешь оправить 2048 байт, а твой сенд вернет тебе 25 байт с положительным результатом.
                      Задача такова - отправлять данные циклично, т е если отправлен чанк - отправлять пока не уйдут дети в школу, все 2048 байт.
                      Либо использовать протоколы более высокого уровня для передачи даты аля http
                        Цитата nemez @
                        progman
                        так должно быть ибо такая архитектура систем.
                        Он не стал колом, а стал ждать когда твой клиент соизволит от сервера забрать данные.
                        У тебя еще есть один серьезный прокол по теме - тебе нужно в цикле, отправлять данные пока они не будут отправлены все.
                        ExpandedWrap disabled
                          int rc = WSASend( m_socket, &dataBuf, 1, &sendBytes, 0, NULL, NULL );

                        не покатит, rc - по факту количество байт или sendBytes - количество байт, реально отправленных твоим сендом.
                        Т.е. ты можешь оправить 2048 байт, а твой сенд вернет тебе 25 байт с положительным результатом.
                        Задача такова - отправлять данные циклично, т е если отправлен чанк - отправлять пока не уйдут дети в школу, все 2048 байт.
                        Либо использовать протоколы более высокого уровня для передачи даты аля http

                        Это я как раз учитываю. и шлю пока не отправится всё
                          progman
                          Если из отправленных 2048 получено 1456 (а это как раз сегмент даты впихиваемый в 1500 байт физического пакета) - значит либо ты остающиеся байты прохлопал в процессе передачи, либо оти ушли в плановые страны на этпае затыка со стороны клиента;
                          Лучший вариант для понимания происходящего в канале - wireshark. Битва экстрасенсов это здорово, а реальное понимание - оно необходимо

                          Цитата Oleg2004 @
                          Ну а все таки как насчет AF_UNSPEC?

                          Oleg2004
                          там недоось винда - ей параллельно, можно писать все что хочешь, и оно будет работать. Правда, непонятно как. Но будет
                            Цитата nemez @
                            progman
                            Если из отправленных 2048 получено 1456 (а это как раз сегмент даты впихиваемый в 1500 байт физического пакета) - значит либо ты остающиеся байты прохлопал в процессе передачи, либо оти ушли в плановые страны на этпае затыка со стороны клиента;
                            Лучший вариант для понимания происходящего в канале - wireshark. Битва экстрасенсов это здорово, а реальное понимание - оно необходимо

                            Ничего я не прохлопал. недостающие 592 читаются следующим запросом WSARecv
                              Цитата nemez @
                              Если из отправленных 2048 получено 1456 (а это как раз сегмент даты впихиваемый в 1500 байт физического пакета)

                              Если точнее, то 1460 байтов. :)
                              Цитата nemez @
                              там недоось винда - ей параллельно, можно писать все что хочешь, и оно будет работать. Правда, непонятно как. Но будет
                              :D
                              Но я бы все равно предпочел точность выбора семейства. ТСР никогда в моем представлении не было "неспециализированным" протоколом.
                              Кстати, не вредно бы было глянуть на MTU системы или рутера.
                              И конечно я бы выбирал такие объемы передачи (блоки), которые точно влазят в один IP-пакет. Для пущей вящности.
                              Сообщение отредактировано: Oleg2004 -
                                Цитата progman @
                                Ничего я не прохлопал. недостающие 592 читаются следующим запросом WSARecv

                                ну так система может разбивать данные на произвольные чанки, хоть по одному байту.
                                Нужно или писать самому более высокоуровневый протокол (изобретать велосипед). Либо испльзовать уже готовый - а ля telnet, HTTP и т.д.
                                Ну у нас по классике - костыли и велосипеды. Костыль - это таймаут после отправки, между слов говоря.

                                Цитата Oleg2004 @
                                которые точно влазят в один IP-пакет

                                ну это колхозинг. Нас не должно интересовать как там оно под капотом работает. Хочу я передавать по 5К дату - мое право, ибо TCP - потоковый протокол. Мы не обязаны вмещать дату в одну датаграмму, да и прямое предназначение TCP - контроль этой самой передачи. 5-10-50-100 - любого количества килобайт-мегабайт
                                  Цитата nemez @
                                  ну это колхозинг. Нас не должно интересовать как там оно под капотом работает. Хочу я передавать по 5К дату - мое право, ибо TCP - потоковый протокол. Мы не обязаны вмещать дату в одну датаграмму, да и прямое предназначение TCP - контроль этой самой передачи. 5-10-50-100 - любого количества килобайт-мегабайт

                                  Ну с этим никто не спорит. :D
                                  Я где нибудь сомневался в потоковости ТСР?
                                  Просто если есть возможность - почему бы и нет? Особенно в связи с серверным взаимодействием, когда команды отдельно, а блоки данных - отдельно...
                                  Но...хозяин - барин. :D
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0411 ]   [ 17 queries used ]   [ Generated: 19.04.24, 12:12 GMT ]