Конференция "Сети" » Время ожидания коннекта сокетом при недоступной сети
 
  • SpellCaster (06.11.07 13:32) [0]
    Всем привет!
    Есть небольшая трабла: если соединение с сетью неактивно или отключено, то попытка соединиться через него затягивается секунд на 10-15, что слишком уж долго. Сокет создаётя с таймаутом 5000, то есть по идее должен вываливаться гораздо раньше. Может, где-то в недрах WinSock-а есть некая глобальная переменная? У кого-нибудь есть идеи?
  • Сергей М. © (06.11.07 13:43) [1]
    Похоже ты путаешь лукап с коннектом
  • DVM © (06.11.07 16:01) [2]

    > SpellCaster

    ждет на функции Connect() ? Если да, то используй неблокирующие сокеты или хотя бы неблокирующий Connect.
  • DVM © (06.11.07 16:02) [3]

    > Сокет создаётя с таймаутом 5000

    Что за сокет ты создаешь? (Компонент или сам). И где ты указал таймаут?
  • SpellCaster (06.11.07 16:40) [4]
    > Сергей М.

    Да нет вроде

    > DVM

    Ага, на ней. Неблоки не хочется, а неблок. коннект нет смысла, т.к. сокет в отдельном треде.

    > Что за сокет ты создаешь? (Компонент или сам).

    Свой класс, простая обёртка над АПИ. Блокирующий сокет, вот кусок кода его создания:

    fSckt:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if fSckt=INVALID_SOCKET then Exit;
    if bind(fSckt,fLocalAddr,SizeOf(TSockAddr))=SOCKET_ERROR then Exit;
    fInTraf:=0; fOutTraf:=0;
    Result:=WinSock.connect(fSckt,tmp_addr,SizeOf(TSockAddr));
    if Result=SOCKET_ERROR then Exit;



    > И где ты указал таймаут?

    Мда, сейчас посмотрел, там у меня таймаут используется только при проверке готовности, т.е. в коннекте он не участвует. Интересно, его вообще можно поменять?
  • DVM © (06.11.07 17:01) [5]

    > а неблок. коннект нет смысла, т.к. сокет в отдельном треде.

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


    > Интересно, его вообще можно поменять?

    Можно. Я вот так делал с неблокирующим режимом (можно и с блокирующим, но с неблок лучше - можно мгновенно прервать коннект)


    function THTTPInputThread.SocketConnect: integer;
    var
     NoBlock: integer;
     Wfd, EFd: TFDSet;
     TimeVal: TTimeVal;
    begin
     Result := socket(AF_INET, SOCK_STREAM, 0);
     if Result = INVALID_SOCKET then
       begin
         Result := -1;
         exit;
       end;

     NoBlock := 1;
     if ioctlsocket(Result, FIONBIO, NoBlock) = SOCKET_ERROR then
       begin
         CloseSocket(Result);
         Result := -1;
         exit;
       end;

     if Connect(Result, FAddr, SizeOf(FAddr)) = SOCKET_ERROR then
       begin
         if WSAGetLastError =  WSAEWOULDBLOCK then
           begin
             while not Terminated do
               begin
                 FD_ZERO(wfd);
                 FD_SET(result, wfd);

                 FD_ZERO(efd);
                 FD_SET(result, efd);

                 TimeVal.tv_sec := 0;
                 TimeVal.tv_usec := 50;

                 case select(0, nil, @wfd, @efd, @TimeVal) of
                   0: sleep(50);
                   1: if FD_ISSET(Result, wfd) then
                        break
                      else
                        if FD_ISSET(Result, efd) then
                          begin
                            NoBlock := 0;
                            ioctlsocket(Result, FIONBIO, NoBlock);
                            CloseSocket(Result);
                            Result := -1;
                            exit;
                          end;
                   SOCKET_ERROR:
                     begin
                       NoBlock := 0;
                       ioctlsocket(Result, FIONBIO, NoBlock);
                       CloseSocket(Result);
                       Result := -1;
                       exit
                     end;
                 end;
               end;
            end
          else
            begin
              NoBlock := 0;
              ioctlsocket(Result, FIONBIO, NoBlock);
              CloseSocket(Result);
              Result := -1;
            end;
       end;

     //Возврат в блокирующий режим
     NoBlock := 0;
     if ioctlsocket(Result, FIONBIO, NoBlock) = SOCKET_ERROR then
       begin
         CloseSocket(Result);
         Result := -1;
       end;
    end;

  • SpellCaster (06.11.07 17:17) [6]
    > Смысл есть, т.к. даже если все помещено в отдельный поток,
    > ты завершения потока не дождешься, пока Connect() не отработает.

    Логично! Ты прав!
    Пример сейчас поковыряю, а пока еще вопрос:

    > можно и с блокирующим, но с неблок лучше - можно мгновенно
    > прервать коннект

    Как с блокирующими сделать?
  • SpellCaster (06.11.07 17:37) [7]
    Кстати, "Result := -1;" легче присвоить в начале функции, а при ошибке просто выходить - сэкономит несколько строчек )).
 
Конференция "Сети" » Время ожидания коннекта сокетом при недоступной сети
Есть новые Нет новых   [134431   +10][b:0][p:0.003]