На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > UDP клиент и сервер на сокетах , 10054 An existing connection was forcibly closed by the remote host.
      Пытаюсь запустить UDP клиент и сервер под нагрузкой. Для этого я гоняю туда сюда пакетик размером 516 байт.
      Приблизительно на 10-ой итерации клиентского цикла, в сервере, в функции recvfrom возникает ошибка 10054:
      Цитата
      An existing connection was forcibly closed by the remote host.

      Подскажите как ее избежать?

      ExpandedWrap disabled
        // КЛИЕНТ
        #include <winsock2.h>
        #include <windows.h>
        #include <stdio.h>
        #include <ctime>
        #include "../test_packet.h"
         
        #pragma comment(lib, "ws2_32.lib")
         
        const int iPackets = 400;
         
        int main(int argc, char *argv[])
        {
            WSADATA wsa;
            if(WSAStartup(0x202, &wsa)!=0)
            {
                printf("ERROR: WSAStartup failed\n");
                return 0;
            }
            int Sock = socket(AF_INET, SOCK_DGRAM, 0);
            if (Sock < 0)
            {
                printf("ERROR: Create socket failed\n");
                return 0;
            }
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(PORT);
            addr.sin_addr.s_addr = inet_addr("127.0.0.1");
         
            char time[10];
            _strtime_s(time);
            printf("Start client: %s\n", time);
            printf("%d packets\n", iPackets);
         
            for(int i = 0; i < iPackets; i++)
            {
                sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0,
                    (sockaddr *)&addr, sizeof(addr));
            }
            closesocket(Sock);
        }


      ExpandedWrap disabled
        // СЕРВЕР
        #include <winsock2.h>
        #include <windows.h>
        #include <stdio.h>
        #include <ctime>
        #include "../test_packet.h"
         
        #pragma comment(lib, "ws2_32.lib")
         
        int main(int argc, char *argv[])
        {
            WSADATA wsa;
            if(WSAStartup(0x202, &wsa)!=0)
            {
                printf("ERROR: WSAStartup failed\n");
                return 0;
            }
            int Sock = socket(AF_INET, SOCK_DGRAM, 0);
            if (Sock < 0)
            {
                printf("ERROR: Create socket failed\n");
                return 0;
            }
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(PORT);
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
            if (bind(Sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
            {
                printf("ERROR: Bind failed\n");
                closesocket(Sock);
                return 0;
            }
         
            char time[10];
            _strtime_s(time);
            printf("Start server: %s\n", time);
         
            while (true)
            {
                sockaddr_in client_addr;
                int client_addr_size = sizeof(client_addr);
         
                char buff[1024];
                int bytes_read = recvfrom(Sock, buff, sizeof(buff) - 1, 0,
                    (sockaddr*)&client_addr, &client_addr_size);
                if (bytes_read < 0)
                {
                    printf("ERROR: Receive data error %d\n", WSAGetLastError());
                    closesocket(Sock);
                    return 0;
                }
                printf("recv %d bytes, ", bytes_read);
                sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0,
                    (sockaddr*)&client_addr, sizeof(client_addr));
            }
            closesocket(Sock);
        }
        А что будет, если попробовать так:
        ExpandedWrap disabled
              for(int i = 0; i < iPackets; i++)
              {
          ::Sleep(200);
                  sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0,
                      (sockaddr *)&addr, sizeof(addr));
              }


        -Added

        И вот так:
        ExpandedWrap disabled
                  printf("recv %d bytes, ", bytes_read);
           
          /*
                  sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0,
                      (sockaddr*)&client_addr, sizeof(client_addr));
          */
        Сообщение отредактировано: ЫукпШ -
          Та же самая ошибка. Но если разместить исходные клиент и сервер на разных машинах, то ошибок нет.
            Цитата =MOHAX= @
            An existing connection was forcibly closed by the remote host.

            В протоколе udp нет понятия CONNECTION - в принципе
            Потому все описание ситуации не соответствует идеям взаимодействия.
            Что-то не так
              Я приложил полный код исходников, может это какой-то глюк на моей машине?
              У меня стоит WinXP SP3. Сейчас попробую запустить этот код под red hat...
                В общем это снова бредовые изыски Мелкософта:
                WinSock Recvfrom() now returns WSAECONNRESET instead of blocking or timing out
                http://support.microsoft.com/default.aspx?scid=kb;en-us;263823
                правда они пишут что эту муть они сделали только под 2000-ный, значит врут


                Принципиально это все-таки возможно – только в одном случае:
                This error is also possible on a datagram socket; for instance, this error could result if your application sends a UDP datagram to a host, which rejects it by responding with an ICMP Port Unreachable.[B]
                  Мде... :huh:
                    Цитата =MOHAX= @
                    Я приложил полный код исходников, может это какой-то глюк на моей машине?
                    У меня стоит WinXP SP3. Сейчас попробую запустить этот код под red hat...

                    Нет, у меня то же самое.
                    Но суть предложения ты похоже не уловил.

                    я предположил, что работа твоей проги слишком
                    "напрягает" компьютер и он попросту не в состоянии
                    обработать такое количество информации.
                    Стоило ослабить нагрузку (уменьшить темп передачи)
                    у меня ошибки прекратились.

                    Не удивительно, что на разных компьютерах эффект пропал.
                    Сообщение отредактировано: ЫукпШ -
                      Цитата ЫукпШ @
                      я предположил, что работа твоей проги слишком
                      "напрягает" компьютер и он попросту не в состоянии
                      обработать такое количество информации.

                      Это безусловно так
                      Стек одного и того же компа вынужден очень быстро реагировать на то, что он сам себе и шлет
                      Потому slep(200)проблемы не решил.
                      Для интереса можно было бы поставить секунду. и более :)
                      Ну и конечно же сама ошибка в микрософтовской интерпретации напрягает :blink:
                        Цитата Oleg2004 @
                        Стек одного и того же компа вынужден очень быстро реагировать на то, что он сам себе и шлет
                        Потому slep(200)проблемы не решил.

                        А если так ?:
                        ExpandedWrap disabled
                              for(int i = 0; i < iPackets; i++)
                              {
                                  WaitTrReady (Sock);
                                  sendto(Sock, TEST_PACKET, TEST_PACKET_SIZE, 0,
                                      (sockaddr *)&addr, sizeof(addr));
                              }
                              
                          // где:
                          bool  WaitTrReady (SOCKET Socket)
                          {
                           bool ReadRDY, bool WriteRDY, bool ErrRDY;
                           bool RetC = false;
                           for(int i=0; i<T_OUT;++i)
                           {
                            if(!SelectOP (Socket, ReadRDY, WriteRDY, ErrRDY)) return false;
                            if(WriteRDY) {RetC = true;break;}
                            ::Sleep(200+i*50);
                           }
                           return RetC;
                          }
                          //....................
                          bool SelectOP (SOCKET Socket, bool& ReadRDY, bool& WriteRDY, bool& ErrRDY)
                          {
                          bool RetC=false;
                          fd_set  ReadS,WriteS,ErrS;
                           
                            ReadRDY   = false;
                            WriteRDY  = false;
                            ErrRDY    = false;
                           
                            FD_ZERO(&ReadS);
                            FD_ZERO(&WriteS);
                            FD_ZERO(&ErrS);
                           
                            FD_SET(Socket, &ReadS);
                            FD_SET(Socket, &WriteS);
                            FD_SET(Socket, &ErrS);
                           
                            SetTimeval ();// установка t-out
                            if(::select(0,&ReadS,&WriteS,&ErrS,&tv)!=SOCKET_ERROR)
                            {
                             if(FD_ISSET(Socket, &ReadS))  {ReadRDY  = true;}
                             if(FD_ISSET(Socket, &WriteS)) {WriteRDY = true;}
                             if(FD_ISSET(Socket, &ErrS))   {ErrRDY   = true;}
                             RetC=true;
                            }
                            return RetC;
                          }
                          Извините, но без комментов к идее разобраться в чужих соображениях очень нелегко, если вообще возможно.
                          Однако позволю себе еще раз напомнить, что в UDP быстрый передатчик подавляет приемник
                          "Уведомление ICMP типа source quench иногда называют также "подавление источника". Его можно рассматривать как примитивный инструмент сдерживания потоков, генерируемых отправителем, но нельзя причислить к эффективным методам контроля за перегрузками. В ранних UNIX-реализациях протоколов TCP/IP ICMP-пакеты этого типа игнорировались. В TCP-реализациях, поддерживающих алгоритм медленного старта, в ответ на это сообщение уменьшается размер "окна перегруженности". UDP-модули игнорируют это сообщение, информируя при этом обслуживаемую прикладную программу о требовании приемника уменьшить интенсивность и/или размер пакетов.Согласно RFC-1812 эта ошибка признана устаревшей"
                          Повидимому та ошибка, о которой шла речь вначале, и призвана для оповещения.......
                            Цитата Oleg2004 @
                            Извините, но без комментов к идее разобраться в чужих соображениях очень нелегко, если вообще возможно.
                            Однако позволю себе еще раз напомнить, что в UDP быстрый передатчик подавляет приемник

                            Извините, что так произошло.
                            В данном случае я пытался предложить перед отправкой
                            сообщения проверить готовность передатчика.
                              Цитата ЫукпШ @
                              В данном случае я пытался предложить перед отправкой
                              сообщения проверить готовность передатчика.

                              А смысл?
                              Если это UDP-сервер, то он всегда готов - так как висит на recvfrom() и ждет вечно......
                              Так что он то готов всегда - если включен
                                Вернемся к исходному коду. Во-первых, поставьте и в цикл сервера и в цикл клиента задержку, хоть какую-то. Смотрите на это хотя бы с той стороны, что это является плохим тоном, т.е. у Вас должно быть представление в какой момент времени от начала секунды что происходит, а в Вашем варианте получается мешанина. А ошибка возникает скорее всего из-за того, что на клиент Вы отправляете данные, но клиентом их не считатываете. По умалчиванию буффер приема, если не ошибаюсь, равен 4096 байт. На 10-й операции у Вас туда пытается записаться 5160 байт, поэтому клиент и отрубается. Правда не могу понять почему на двух разных компьютерах этого не происходит <_< Юзайте setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)) и setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size))

                                PS И еще WSACleanup() забыли ;)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0635 ]   [ 16 queries used ]   [ Generated: 25.04.24, 11:43 GMT ]