[Delphi] Ошибка 10035 при запросе на HTTP сервер через WinSock

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Rastamanka, 27 Jan 2018.

  1. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Добрый день имеется вот такой код.
    Проверка на открытый порт происходит успешно, а когда надо получить ответ то WinSock возвращает ошибку 10035.
    Вообще задача получить не всю страницу, а достаточно только Headers.
    В первую очередь важна скорость.

    Code:
    function TCheckerThread.CheckPort: Boolean;
    var
      s, opt, BytesRead: Integer;
      FSocket: TSOCKET;
      addr: TSockAddr;
      hEvent: THandle;
      fset: TFDset;
      tv: TTimeval;
      Get, Response: string;
    begin
      Result := false;
    
      addr.sin_family := AF_INET;
      addr.sin_addr.s_addr := INADDR_ANY;
    
      addr.sin_addr := IP; 
    
      hEvent := WSACreateEvent();
      FSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    
      try
        if (FSocket = INVALID_SOCKET) then
        begin
          Result := True;
          Exit;
        end;
    
        WSAEventSelect(FSocket, hEvent, FD_WRITE + FD_CONNECT);
    
        addr.sin_port := Port;
    
        connect(FSocket, @addr, sizeof(addr));
    
        if (WSAGetLastError() = WSAEINPROGRESS) then
        begin
          Result := true;
          Exit;
        end;
    
        FD_Zero(fset);
        FD_SET(FSocket, fset);
    
        tv.tv_sec := 1;
        tv.tv_usec := 0;
    
        s := select(1, nil, @fset, nil, @tv);
    
        if (not FD_ISSET(FSocket, fset)) then
        begin
          Result := true;
          Exit;
        end;
    
        s := Sizeof(opt);
        opt := 1;
    
        getsockopt(FSocket, SOL_SOCKET, SO_ERROR, @opt, s);
    
        if (opt <> 0) then
        begin
          Result := true;
          Exit;
        end;
    
     ToDebug('Port opened');
    
        Get := Format('GET / HTTP/1.1'#13#10 + 'Host: %s'#13#10 + 'User-Agent: %s'#13#10 + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'#13#10 + 'Accept-Language: en-US,en;q=0.5'#13#10 + 'Accept-Encoding: gzip, deflate'#13#10 + 'Connection: keep-alive'#13#10 + #13#10, [IpStr, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0']);
    
        if Send(FSocket, PChar(Get)^, Length(Get), 0) = SOCKET_ERROR then
        begin
          Result := True;
          Exit;
        end;
    
        SetLength(Response, 65536);
        BytesRead := Recv(FSocket, PChar(Response)^, 65536, 0);
    
        case BytesRead of
          -1:
            ToDebug('Recv error: ' + IntToStr(WSAGetLastError));
          0:
            ToDebug('Connection closed by peer');
        else
          Response[BytesRead] := #0;
          ToDebug('Response: ' + Response);
        end;
    
      finally
        if closesocket(FSocket) <> 0 then
          ToDebug('Error closed socket');
        WSACloseEvent(hEvent);
      end;
    end;
     
  2. nikbim96

    nikbim96 Member

    Joined:
    16 Jan 2014
    Messages:
    112
    Likes Received:
    22
    Reputations:
    1
    10035 WSAEWOULDBLOCK Resource temporarily unavailable (Ресурс временно недоступен).
    Эта ошибка возвращается операциями с неблокирующими сокетами, которые не могут быть немедленно завершены. Это не фатальная ошибка. Обычно WSAEWOULDBLOCK возвращается как результат вызова connect() на неблокирующем сокете SOCK_STREAM, поскольку для установления соединения требуется некоторое время.

    По пробуй обрати внимание на свой код в Socket tv.tv_sec := 1; и tv.tv_usec := 0; пробуй изменить возможно не успевает ответить, за такой короткий промежуток и не дожидается завершения таймаута.
     
    Rastamanka likes this.
  3. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Ну это не вариант т.к. тогда очень долго проверяется открыт порт или нет.

    Сейчас сделала вот так. Но считаю это не правильный вариант. Может есть какой-то лучше способ для этого? К примеру так же поставить евент до ожидания когда можно получить ответ.
    Code:
        repeat
        BytesRead := Recv(FSocket, PChar(Response)^, 65536, 0);
    
        case BytesRead of
          -1:
            Sleep(500);
            //ToDebug('Õîñò ' + IpStr + ' Recv error: ' + IntToStr(WSAGetLastError));
          0:
            ToDebug('Connection closed by peer');
        else
          Response[BytesRead] := #0;
          ToDebug('Õîñò ' + IpStr + ' îòâå÷àåò ' + Response);
        end;
        until WSAGetLastError <> WSAEWOULDBLOCK;
     
    #3 Rastamanka, 27 Jan 2018
    Last edited: 27 Jan 2018