Uwaga: Pozwól mi przeprosić za długość tego pytania, musiałem włożyć do niego wiele informacji. Mam nadzieję, że to nie spowoduje, że zbyt wielu ludzi po prostu przejrzy i przyjmie założenia. Proszę przeczytać w całości. Dzięki.Jaka jest dobra metoda obsługi sieciowych strumieni We/Wy?
Mam strumień danych przychodzących przez gniazdo. Te dane są zorientowane liniowo.
Używam APM (Async Programming Method) .NET (BeginRead, etc ..). Wyklucza to używanie operacji we/wy opartych na strumieniu, ponieważ Asynchroniczne operacje we/wy są oparte na buforze. Możliwe jest przepakowanie danych i wysłanie ich do strumienia, takiego jak strumień pamięci, ale są tam również problemy.
Problem polega na tym, że mój strumień wejściowy (który nie mam nad nim kontroli) nie daje mi żadnych informacji o tym, jak długi jest strumień. To po prostu jest strumieniem linii nowej linii wygląda tak:
COMMAND\n
...Unpredictable number of lines of data...\n
END COMMAND\n
....repeat....
Tak, używając APM, a ponieważ nie wiem, jak długo dana zestaw danych będzie, to jest prawdopodobne, że bloki danych przetnie bufor granice wymagające wielu odczytów, ale te wielokrotne odczyty będą obejmowały również wiele bloków danych.
przykład:
Byte buffer[1024] = ".................blah\nThis is another l"
[another read]
"ine\n.............................More Lines..."
My pierwsza myśl było użyć StringBuilder i po prostu dodać do linii bufor do SB. Działa to w pewnym stopniu, ale było mi trudno wyodrębnić bloki danych. Próbowałem użyć StringReader do odczytu nowych danych, ale nie było sposobu, aby dowiedzieć się, czy otrzymujesz kompletną linię, czy nie, ponieważ StringReader zwraca częściową linię na końcu ostatniego dodanego bloku, a następnie powraca null na końcu. Nie ma sposobu, aby dowiedzieć się, czy zwrócono całkowicie nową linię danych.
Przykład:
// Note: no newline at the end
StringBuilder sb = new StringBuilder("This is a line\nThis is incomp..");
StringReader sr = new StringReader(sb);
string s = sr.ReadLine(); // returns "This is a line"
s = sr.ReadLine(); // returns "This is incomp.."
Co gorsza, jest to, że jeśli po prostu zachować dodanie do danych, bufory stają się coraz większe i większe, a ponieważ może to trwać kilka tygodni lub miesięcy, w czasie, który nie jest dobry rozwiązanie.
Moją kolejną myślą było usunięcie bloków danych z SB, kiedy je czytałem. Wymagało to napisania mojej własnej funkcji ReadLine, ale utknąłem blokując dane podczas odczytu i zapisu. Ponadto, większe bloki danych (które mogą składać się z setek odczytów i megabajtów danych) wymagają skanowania całego bufora w poszukiwaniu nowych linii. To nie jest wydajne i dość brzydkie.
Szukam czegoś, co ma prostotę StreamReader/Writer z wygodą asynchronicznego I/O.
Moja następna myśl polegała na użyciu obiektu MemoryStream i zapisaniu bloków danych do strumienia pamięci, a następnie dołączeniu StreamReadera do strumienia i skorzystaniu z ReadLine, ale znowu mam problemy ze stwierdzeniem, czy ostatni odczyt w buforze jest kompletną linię lub nie, a jeszcze trudniej jest usunąć "nieaktualne" dane ze strumienia.
Myślałem również o używaniu wątku z synchronicznymi odczytami. Ma to tę zaletę, że przy użyciu StreamReadera, zawsze zwróci pełną linię z ReadLine(), z wyjątkiem zerwanych sytuacji połączenia. Ma to jednak problemy z anulowaniem połączenia, a niektóre rodzaje problemów sieciowych mogą powodować zawieszanie blokujących gniazd przez dłuższy czas. Używam asynchronicznej operacji wejścia, ponieważ nie chcę powiązywać wątku przez cały czas blokowania programu podczas odbierania danych.
Połączenie jest długotrwałe.Dane będą nadal płynąć z czasem. Podczas początkowego połączenia istnieje duży przepływ danych, a po wykonaniu tego przepływu gniazdo pozostaje otwarte, czekając na aktualizacje w czasie rzeczywistym. Nie wiem dokładnie, kiedy początkowy przepływ został "zakończony", ponieważ jedynym sposobem, aby się dowiedzieć, jest to, że nie są już wysyłane żadne dane. Oznacza to, że nie mogę się doczekać, aż wstępne ładowanie danych zostanie zakończone przed przetworzeniem, prawie utknąłem przetwarzanie "w czasie rzeczywistym", jak to jest.
Czy ktoś może zaproponować dobrą metodę radzenia sobie z tą sytuacją? w sposób, który nie jest zbyt skomplikowany? Naprawdę chcę, żeby to było tak proste i eleganckie, jak to tylko możliwe, ale wciąż wymyślam coraz bardziej skomplikowane rozwiązania ze względu na wszystkie przypadki skrajne. Domyślam się, że chcę czegoś w rodzaju FIFO, w którym mogę łatwo dołączyć więcej danych, jednocześnie wyskakując z niego dane, które pasują do pewnych kryteriów (np. Ciągi zakończone znakiem nowej linii).
Pomyślałem, że to także interesujący problem, dlatego napisałem post o rozwiązaniu go z CCR, który można znaleźć na stronie http: //iodyner.spaces.live.com, jeśli jesteś zainteresowany ... –