2011-07-07 21 views
7

Ten kod jest na serwerze HTTPS za pomocą gniazd blokujących:Dlaczego to wywołanie SSL_pending zawsze zwraca zero?

request := ''; 
    start := gettickcount; 
    repeat 
    if SSL_pending(ssl) > 0 then 
     begin 
     bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1); 
     if bytesin > 0 then 
     begin 
     buffer[bytesin] := #0; 
     request := request + buffer; 
     end 
     else break; // read failed 
     end; // pending 
    until (gettickcount - start) > LARGETIMEOUT; 
    // "request" is ready, though possibly empty 

SSL_pending() zawsze zwraca zero i SSL_read() nigdy nie zostanie osiągnięty. Jeśli wywołanie SSL_pending() zostanie usunięte, wykonywana jest funkcja SSL_read(). Dlaczego funkcja SSL_pending() nie wskazuje, ile bajtów jest dostępnych?

Należy zauważyć, że jeśli wywołasz funkcję SSL_read(), a liczba zwróconych bajtów jest mniejsza niż rozmiar bufora, przeczytałeś wszystko i skończyłeś.

Jeśli dane przychodzące są większe niż rozmiar bufora, pierwsze wywołanie funkcji SSL_read() wypełnia ten bufor i można powtórzyć wywołanie funkcji SSL_read(), dopóki nie można wypełnić bufora.

ALE jeśli przychodzące dane są dokładną wielokrotnością rozmiaru bufora, ostatnia porcja danych wypełnia bufor. Jeśli spróbujesz innego myślenia SSL_read(), może istnieć więcej danych na gnieździe blokującym, zawiesza się w nieskończoność. W związku z tym należy najpierw sprawdzić właściwość SSL_pending(). Jednak wydaje się, że to nie działa.

Jak uniknąć zawieszenia na ostatnim SSL_read()? (Nie mogę sobie wyobrazić, że odpowiedź nie będzie blokować, ponieważ oznacza to, że nie można nigdy używać SSL_read z blokowaniem.)

AKTUALIZACJA: Następujące prace. Widocznie SSL_pending() nie działa dopiero po pierwszym SSL_read():

request := ''; 
    repeat 
    bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1); 
    if bytesin > 0 then 
     begin 
     buffer[bytesin] := #0; 
     request := request + buffer; 
     end 
    else break; // read failed 
    until SSL_pending(ssl) <= 0; 
    // "request" is ready, though possibly empty 

Odpowiedz

5

Używasz SSL_pending() całkowicie niewłaściwy sposób. OpenSSL używa maszyny stanu, gdzie SSL_pending() wskazuje, czy automat stanów ma oczekujące bajty, które zostały zbuforowane i oczekują na przetworzenie. Ponieważ nigdy nie dzwonisz pod numer SSL_read(), nigdy nie buforujesz żadnych danych ani nie przesuwasz stanu maszyny.

+7

Dokumentacja dla SSL_pending z pewnością nie wyjaśnia tego. –

+0

W pewnym sensie: "uzyskaj liczbę czytelnych bajtów zbuforowanych w obiekcie SSL ... dane mogą być buforowane w ssl i są gotowe do natychmiastowego pobrania z SSL_read (3)" –

2

Jeśli funkcja zwalniająca SSL zwraca kod powrotu 0, to niekoniecznie oznacza, że ​​nie ma danych natychmiast dostępnych do odczytania w sesji SSL. Kod powrotu 0 wskazuje, że nie ma więcej danych w bieżącym rekordzie danych SSL. Jednak więcej rekordów danych SSL mogło już zostać odebranych z sieci. Jeśli funkcja SSL_pending zwraca kod powrotu 0, uruchom funkcję select, przekazując deskryptor pliku gniazda, aby sprawdzić, czy gniazdo jest czytelne. Czytelny oznacza, że ​​więcej danych zostało odebranych z sieci w gnieździe.

Powiązane problemy