2009-10-07 14 views
9

Kiedy wysyłam()/zapisuję() wiadomość przez strumień TCP, jak mogę sprawdzić, czy te bajty zostały pomyślnie dostarczone?Sprawdzanie, czy został dostarczony komunikat dotyczący tcp.

Odbiornik potwierdza odbiór bajtów przez tcp, więc stos tcp nadawców powinien znać.

Ale kiedy wysyłam() niektóre bajty, send() natychmiast zwraca, nawet jeśli pakiet nie mógł (jeszcze) być dostarczony, przetestowałem to na Linuksie 2.6.30 używając strace na netcat, wyciągając mój kabel sieciowy przed wysyłanie niektórych bajtów.

Właśnie opracowuję aplikację, w której bardzo ważne jest, aby wiedzieć, czy wiadomość została dostarczona, ale wdrożenie funkcji tcp ("ack dla wiadomości # 123") wydaje się niezręczne, musi istnieć lepszy sposób.

Odpowiedz

19

wysyłająca TCP wie, kiedy dane zostaną potwierdzone przez drugiego końca, ale tylko dlatego, że nie jest to tak, że wie, kiedy może odrzucić dane (ponieważ ktoś inny jest teraz odpowiedzialny za przesłanie go do aplikacji po drugiej stronie).

Zazwyczaj nie dostarcza tych informacji do aplikacji wysyłającej, ponieważ (wbrew pozorom) faktycznie nie byłaby to średnia wiele dla aplikacji wysyłającej. Potwierdzenie nie oznacza, że ​​aplikacja odbierająca ma dane i zrobiła z tym coś sensownego - wszystko to znaczy, że wysyłający TCP nie musi się już o to martwić. Dane mogą nadal być przesyłane - na przykład na pośrednim serwerze proxy lub w odbierającym stosie TCP.

"Dane pomyślnie odebrane" są w rzeczywistości koncepcją na poziomie aplikacji - co to oznacza w zależności od aplikacji (na przykład w przypadku wielu aplikacji sensowne byłoby uznawanie danych "otrzymanych" po ich zsynchronizowaniu z dysk po stronie odbiorczej). Oznacza to, że musisz go zaimplementować sam, ponieważ jako programista aplikacji naprawdę jesteś jedynym, który potrafi wiedzieć, jak zrobić to rozsądnie dla swojej aplikacji.

8

Odebranie odbiorcy potwierdzenia to najlepszy sposób, nawet jeśli "czuje się niezręcznie". Pamiętaj, że IP może rozbić twoje dane na wiele pakietów i ponownie je złożyć, i to może być wykonane wiele razy wzdłuż transmisji, jeśli różne routery na drodze mają różne MTU, więc twoja koncepcja "pakietu" i TCP może się nie zgadzać.

Znacznie lepiej wysłać "pakiet", niezależnie od tego, czy jest to ciąg znaków, obiekt serializowany, czy dane binarne, i czy odbiornik powinien wykonać wszystkie czynności, które trzeba wykonać, aby go uruchomić, a następnie odesłać potwierdzenie.

+0

Fakty są słuszne, ale nie podoba mi się frazowanie. TCP jest niezawodnym protokołem, ** usłyszysz o nim, jeśli transmisja się nie powiedzie. Fakt, że nie trzeba żądać potwierdzenia ACK od strony zdalnej, to funkcja, a nie błąd. "Najlepszym" sposobem radzenia sobie z tym jest ** ignorowanie ** problemu na poziomie wywołań systemowych i bajtów. Jeśli potrzebujesz wyniku, zrób to na poziomie protokołu, a nie gniazd. –

6

Protokół TCP bardzo utrudnia uzyskanie danych. Jeśli występuje problem z siecią, przesyła ona kilka razy dane. Oznacza to, że wszystko, co wysyłasz, jest buforowane i nie ma w porę, aby upewnić się, że dotarło (opóźnienie będzie 2 minuty później, jeśli sieć nie działa).

Jeśli potrzebujesz szybkiej reakcji, użyj protokołu UDP. Nie używa żadnego z narzutów TCP, ale sam musisz poradzić sobie z wszystkimi problemami.

+0

Tak, według projektu jest niezawodny i uporządkowany – RichardOD

3

Warstwa aplikacji nie ma kontroli nad powiadomieniami na niższych warstwach (na przykład w warstwie transportowej), chyba że są one wyraźnie określone - jest to zgodne z projektem. Jeśli chcesz wiedzieć, co robi TCP na poziomie jednego pakietu, musisz dowiedzieć się na warstwie, na której działa TCP; oznacza to obsługę nagłówków TCP i danych ACK.

Jakikolwiek protokół, którego używasz do przenoszenia swojej ładowności, może być jednak używany do przesyłania komunikatów tam iz powrotem za pośrednictwem tego ładunku. Więc jeśli czujesz się niezręcznie używając bitów nagłówka TCP, po prostu ustaw go w swojej aplikacji. Na przykład:

A: Send 450 Bytes 
B: Recv 450 Bytes 
B: Send 'I got 450 Bytes' 
A: Recv 'B got the full message' 
A: Continue 
1

To może brzmieć jak SCTP. Myślę, że powinno to wspierać to, co chcesz. Alternatywą wydaje się, aby przejść do UDP, a jeśli przełączanie protokołów zresztą ...

3

Nawet jeśli dotarł aż do warstwy TCP, nie ma gwarancji, że nie znajduje się w buforze aplikacji, a następnie aplikacja uległa awarii zanim mogła go przetworzyć. Użyj potwierdzenia, to wszystko, co robi (np. SMTP).

Powiązane problemy