Warunki do HTTP persistent connections

0

Witam

Nie wiem, czy to jest odpowiednia grupa forum do zadania tego pytania, ale najwyżej wątek zostanie przeniesiony.

Piszę serwer https://github.com/overcq/ouxa opartym na C (https://github.com/overcq/oux, a serwer to https://github.com/overcq/oux/tree/master/program/web-srv). Jednak mam pewien problem.

Uruchamiam serwer na localhost, ustawiony do katalogu, gdzie jest zainstalowany Wordpress, i patrzę do logu serwera na bieżące nadchodzące i obsługiwane połączenia. Okazuje się, że przychodzi co najwyżej jedno, a rzadko kiedy drugie połączenie, ale po każdej transmisji jednego żądania HTTP serwer czeka na wysłanie kolejnego żądania przez klienta, lecz upływa limit czasu (5 sekund) i serwer rozłącza się, a wtedy następuje kolejne połączenie od klienta.
Z tego powodu też na stronie diagnostycznej Wordpress wypisuje błędy krytyczne, że upłynął limit czasu 10001 milisekund na żądanie REST API. Nie wspominając nawet o tym, że strony wczytuje długo.

Jak można zobaczyć w logu (https://4programmers.net/Pastebin/15676), klient żąda HTTP/1.1 i serwer odpowiada tym samym, a ponadto na wszelki wypadek też jest wysyłane Connection: keep-alive. Jednak nadal przeglądarka www trzyma połączenie, a nie wysyła żadania. Testowałem na Firefox i Chromium.
Kolejny warunek: Content-Length. Jest ono wysyłane dla statycznych plików, a dla skryptów, dla których serwer uruchamia PHP przez CGI, jest używany Transfer-Encoding: chunked. I w tym ostatnim przypadku klient czasem wysyła drugie żądanie na tym samym połączeniu.

Jakie muszą być spełnione warunki, by persistent connections były przez przeglądarkę www obsługiwane? A może gdzieś popełniam błąd przy wysyłaniu odpowiedzi?
I drugie pytanie. Po których statusach odpowiedzi (np. HTTP/1.1 500, HTTP/1.1 400) z serwera musi następować rozłączenie? A może nie ma takiej specyfikacji i wszystko zależy od klienta i serwera?

1

Okazuje się, że przychodzi co najwyżej jedno, a rzadko kiedy drugie połączenie, ale po każdej transmisji jednego żądania HTTP serwer czeka na wysłanie kolejnego żądania przez klienta, lecz upływa limit czasu (5 sekund) i serwer rozłącza się, a wtedy następuje kolejne połączenie od klienta.

Być może Twój serwer uważa, że wysłał całą odpowiedź a przeglądarka niekoniecznie? Jeśli przeglądarka widzi połączenie keep-alive to zanim wyśle po nim drugi request musi poczekać aż pierwszy się skończy. Request jest zakończony kiedy całe response body od serwera jest przeczytane, czyli:

  • w response jest podane Content-Length - przeglądarka musi przeczytać dokładnie tyle bajtów odpowiedzi
  • nie ma Content-Length ale jest Transfer-Encoding: chunked - koniec odpowiedzi jest wtedy, gdy przyjdzie specjalny chunk "zero"

Więc kiedy jeśli w pierwszym przypadku serwer faktycznie wyśle mniej bajtów niż zdefiniował w Content-Length, połączenie będzie wisiało aż do timeoutu. Często takie błędy wynikają z kodowania / kompresji / buforowania czegoś po stronie serwera. W drugim przypadku jeśli nie wyślesz terminalnego chunka, połączenie też się zwiesi.

Nie wiem czy któryś z tych przypadków występuje u Ciebie, bo ten log ciężko czytać - wytnij z niego część która rzeczywiście odpowiada sytuacji którą opisałeś. Spójrz też na zakładkę sieciową w debug tools przeglądarki która wysyła request. Możesz też spróbować użyć curl w trybie verbose.

Co do standardów to powinieneś się trzymać RFC -> https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html (nie wiem czy aktualne)

0

Błąd polegał na tym, że przeglądarka www chciała nawiązać kolejne połączenia, a serwer ich nie odbierał, i na tym się blokowała. Po zmianach działa. I dzięki za link. Z treści wynika, że po dowolnych statusach HTTP może być zachowane persistent connection.

1 użytkowników online, w tym zalogowanych: 0, gości: 1