2012-09-28 9 views
5

Pracuję nad utworzeniem serwera proxy, który nasłuchuje na określonym porcie dla połączeń przychodzących. Połączenia są zwykle Żądaniami Http (GET/POST). Nie wolno decydować, czy wybrać HttpListener czy Sockets. Będę modyfikował HttpRequests w proxy, a następnie przekazywał go do miejsca docelowego.Gniazda kontra HttpListener

Kiedy wolisz HttpListener zamiast Sockets. Jakie są zalety każdego z nich?

+0

analizowaniem/Modyfikacja nagłówka HTTP, czytania treści, obsługi pakietowego transferu itp są znacznie prostsze z HttpListener. –

+0

Jakie modyfikacje zamierzasz wprowadzić do HttpRequests? –

+0

Będę zmieniać HostHeader, przekierowuję niektóre żądania itp. – NewUnhandledException

Odpowiedz

13
  • Zalety HttpListener
    • umożliwia udostępnianie portu z innych procesów wykorzystujących http.sys (w tym przy użyciu HttpListener lub IIS, dopóki prefiksy są unikalne)
    • Http.sys wykorzystuje I/O Porty ukończenia dla ciebie; jest to bardzo trudne do ustawienia, które się samemu bez użycia TcpListener
    • HttpListener analizuje nagłówki HTTP i tworzy nagłówki HTTP na odpowiedź
    • Daje zestaw klas, które są bardzo podobne do tych, w ASP.NET, która wystawiać nagłówki, ciastka, itp
  • Wady HttpListener
    • MAJOR - Localhost klient wysyłanie dużych ładunków poprzez HTTP powoduje kilka dodatkowych kopii tych ładunków, które należy wprowadzić w porównaniu do TcpListener lub Mono HttpListen er w systemie Windows. Należy unikać wysyłania dużych (np. Ponad 5 MB) ciał POST między procesami na tym samym komputerze, jeśli wymagana jest maksymalna przepustowość na procesor. Rozważ użycie plików odwzorowanych w pamięci (w zasadzie pamięć współdzielona). Te dodatkowe kopie nie stanowią problemu, gdy klient i serwer znajdują się na różnych maszynach.
    • Nie zezwala na wyraźną kontrolę czasu otwarcia gniazda TCP; http.sys zarządza tym dla ciebie (nie jest to zwykle ogromna wada, ale jest to po prostu coś, o czym warto wiedzieć)
    • Wszelkie błędy w klasie nagłówków/ciasteczek cię ugryzą; taki jak problem, w którym ustawienie wielu plików cookie spowoduje, że HttpListener zwróci pojedynczy nagłówek Set-Cookie z wieloma plikami cookie, które IE obsłuży, ale Chrome całkowicie je zignoruje (musisz wtedy ręcznie przesuwać pliki cookie i dodawać własne ustawienia) nagłówek Cookie do pracy wokół tego)
  • zalety TcpListener
    • jak HttpListener ta implementuje I/o dopełniania Porty dla Ciebie
    • Jeśli chcesz zrobić coś raz na połączenie (jak czekiem auth), możesz to zrobić, ponieważ wiesz, kiedy gniazdo jest otwarte; Jednak może nie chcą polegać na to z innych powodów (proxy i równoważenia obciążenia może wysyłać prośby wielu użytkowników w tym samym gnieździe)
  • Wady TcpListener vs.HttpListener
    • Musisz dostarczyć parsera nagłówka HTTP
    • Musisz potwierdzić, że żądanie HTTP jest ważne
  • Zalety toczenia to 100% na własnym
    • Żaden że można pomyśleć, w porównaniu do korzystania z TcpListener
  • Wady toczenia tego 100% na własne
    • Najprawdopodobniej wprowadzisz wiele niepotrzebnych/nieprawidłowych blokad w warstwie sieci, co nie spowoduje żadnych problemów podczas testowania wydajności pojedynczego żądania naraz, ale spowoduje, że wydajność pod obciążeniem naprawdę ucierpi. To zajmie trochę czasu, aby je znaleźć i naprawić.
    • Zrobiliśmy to samodzielnie na projekcie i osiągnęliśmy tę samą wydajność, co HttpListener, z wieloma innymi miesiącami kodowania i wynikającą z tego bazą kodową, która była nieosiągalna. Usunęliśmy to i zastąpiliśmy cały kod niestandardowy HttpListener bez żadnego negatywnego wpływu na wydajność i ze znacznie mniejszym kodem do utrzymania.

listopada 2016 Aktualizacja: HttpListener działa bardzo dobrze podczas odbierania ruchu z urządzeń zdalnych. Jednak HttpListener jest złym wyborem, pod względem wydajności, dla dużych ładunków, gdy klient jest na lokalnym hoście. Powodem tego jest częściowo dlatego, że HttpListener używa http.sys, który jest modułem jądra, i najwyraźniej implementacja powoduje wykonanie kilku dodatkowych kopii danych treści. Na przykład, skopiowanie 100 MB z jednej tablicy do innej tablicy w języku C# zajmuje 35 ms, podczas gdy OGŁASZANIE 100 MB z lokalnego klienta do HttpListener zajmuje 350 ms (tak, 10x dłużej). Przejście do HttpListener Mono w tym przypadku skraca czas do 250 ms. Używanie TcpListener z klientem Socket trwa 180 ms. Zamiana wykorzystania gniazd dla CircularBuffer za pomocą MemoryMappedFiles trwa 55 ms. W związku z tym HttpListener nie działa tak dobrze dla dużych ładunków, gdy dostęp z lokalnego komputera. Uwaga: jeśli spróbujesz odtworzyć to badanie, musisz zachować ostrożność, aby zmierzyć różnicę czasu. Stern zaczyna wysyłać dane i gdy tablica kończy się w procesie odbierania, ponieważ niektóre metody wysyłania/zapisywania zwracają się niemal natychmiast, bez wysyłania jakichkolwiek danych (co można udowodnić, wysyłając tablicę zer, a następnie pisząc z nich tył tablicy do przodu, otrzymasz prawie wszystkie, udowadniając, że dane nie zostały wysłane długo po przywróceniu funkcji).

Więcej szczegółów na temat lokalnego deficytu wydajności maszynowego HttpListener vs Mono HttpListener z jednym z moich kolegów tutaj: https://www.linkedin.com/pulse/http-inefficiency-dominika-blach

+0

Dobra odpowiedź. W moim przypadku zastanawiam się, dlaczego moi klienci przestają wysyłać wiadomości po kilkuset połączeniach. Używam HttpListener dla serwera i WebRequest dla klientów. Po pewnym czasie po prostu zatrzymują się, nie ma błędów, wygląda na to, że żadne zasoby nie były dostępne. Odtwarzanie z 'ServicePointManager.DefaultConnectionLimit' i' ServicePointManager.MaxServicePoints' nie pomaga, więc po kilkuset połączeniach otrzymałem ten sam błąd. Próbowałem z KeepAlive, ale bez powodzenia. Dowolny pomysł? Dzięki. – GBrian

+2

Najprawdopodobniej nie zamykasz prawidłowo żądania i odpowiedzi na jednym lub obu końcach, lub użyłeś puli wątków (takiej jak przy użyciu licznika czasu) po stronie klienta i wysyłasz wyjątek z tego wątku puli wątków. Gdy wątek puli wątków nigdy nie zostanie odtworzony. Kiedy skończy się wątek puli wątków, nic, co ich używa, takich jak obiekty Timera, przestanie działać. – huntharo

+0

Sprawdź kod przykładowy HttpListener, który zamieściłem jako odpowiedź na poniższe pytanie. Sprawdź, czy obsługujesz żądania w ten sam sposób, lub wykorzystaj go do utworzenia nowej wersji serwera i sprawdź, czy problem nadal występuje. http://stackoverflow.com/questions/10485985/bad-performance-when-offering-files-to-download-with-httplistener/19202175#19202175 – huntharo