NIO wysyłanie obiektu przez kanał

0

Witam!

Stanąłem przed problemem wysyłania obiektów, a w sumie to czegokolwiek przy użyciu java.nio.Channels
i jest nim to, że (na stan mojej dzisiejszej wiedzy tak mi się wydaje) kanały nie dają mi pewności czy dane które wysyłam doszły w całości tak jak dzieje się to w przypadku socketów. Z prostej przyczyny, którą jest to, że sockety są blokujące mam tam pewność, że to co wyciągam z jego inputStreama jest w pełni kompletne. Tutaj w przypadku kanałów nie mam takiej pewności. I moje pytanie:
co zrobić, żeby wczytać całe dane i żebym miał pewność że są kompletne??

Bardzo proszę o pomoc, bo problem wydaje się być nietrywialny, a nie mogę sobie poradzić:/

Pozdrawiam i z góry dziekuje!

0

Sumy kontrolne. Jeżeli obiekt przeszedł kompletny to jego hashCode powinien być identyczny jak oryginalnego obiektu.

0

to już coś daje:) mam tylko jedno ale:P przecież sumę kontrolną też muszę przesłać, bo inaczej nie będę wiedział czy się zgadza, a tutaj problem wciąż ten sam, bo mogę jej w całości nie dostać.

0

To nie jest akurat problem. Jeżeli suma kontrolna nie zgadza się z obiektem to oznacza, że całość jest nieprawidłowa i transmisję należy powtórzyć.

Tak mi jeszcze jedna myśl przyszła do głowy. Wystarczy, że zamiast obiektu prześlesz obiekt zaszyfrowany choćby w najprostszy sposób (nawet za pomocą base64). W takim wypadku w trakcie odszyfrowywania będzie sprawdzona spójność danych ponieważ inaczej się nie da. Jeżeli użyjesz base64 to znowuż stracone dane spowodują, że nie będzie można zdeserializować obiektu, a nieudana deserializacja oznacza, że obiekt nie jest kompletny.
Narzut związany z szyfrowaniem/rozszyfrowaniem można ograniczyć do minimum stosując jakieś bardzo proste funkcje.

0

hmm. nie do końca wiem czy się rozumiemy. pomysł z sumą kontrolną nie jest zły. tylko nie porównam żadnej sumy jak jej nie wyśle takiej jaka miała być.

Sockety javove, jako że są blokujące czekają aż wszystkie dane dotrą do InputStreama czy innego streama (pewność tego, że dojdą daje mi TCP) i wtedy mam wszystko co wyslalem.

W przypadku kanałow, to tak jak bym lał wode z kubła do rynny, gdzie po srodku jest dziura, a ktos na dole nie wie ile ja mu wleje. I teraz zakladam ze ten na dole ma dostac 1 litr (ale wiem o tym tylko ja).
po srodku mam dziure i mi pol litra wywialo, a gosc na dole dostal drugie pół. W tym wypadku bedzie myslal ze to wszystko, bo dopiero za chwile ja (zakladam ze wiem ze dostal za malo - robie troche za takie TCP :P )
bede mogl mu dolac reszte.

musialem tak na wyobraznie wplynac, bo to obrazuje o co mi chodzi.

wysylam klientem obiekt np. 512bajtow a server ma odebrac wszystko, a sytuacja jest taka, ze wysylam i dajmy na to (co sie dosc czesto zdarza ) nie przychodzi mi caly obiekt tylko jego poczatkowa czesc, selektor odebral ze wiadomosc ze cos przyszlo i odbieram ten kawalek.
teraz sytuacja staje sie taka, ze z tym co dostalem nic nie zrobie, a selektor jak bedzie wolal znowu ze moze czytac, to juz nie wiem czy doszla dalsza czesc, czy klient napisal juz cos nowego, albo tez jeszcze inny klient mi cos wyslal...

0

Nie ma potrzeby wiedzieć czy suma przysłana jest poprawna. Po to wymyślono np. md5 jeżeli coś się różni w niewielkim stopniu to suma nie będzie się zgadzać. Nieważne czy suma jest zła czy obiekt.

0

z tym ze md5 dziala na zasadzie porównywania sum. a przeciez nie bede sumy do serwera listem przesyłał. tak czy inaczej server musi miec ta sume wygenerowana przez klienta zeby sobie sprawdzic czy obiekt jest ten sam. a ja nie będę wysyłał zawsze tego samego obiektu, bo jego zawartość może się zmieniać, gdyż klient będzie na nim różne modyfikacje robił.

mógłbym tak zrobić gdybym z góry wiedział co klient do mnie prześle, a tego nie wiem.

0

To niech klient porównuje:

package pl.koziolekweb.programmers.t155092;

import java.io.Serializable;

public class Opakowywacz<T extends Serializable> implements Serializable {
	
	private T object;
	
	private byte[] md5Sum;
	
	public Opakowywacz(T object){
		this.object = object;
		this.md5Sum = calculateSum(object);
	}

	public static byte[] calculateSum(Serializable object) {
		// liczy sumę
		return null;
	}
// gettery BEZ setterów
}

Z serwera wysyłasz takie coś. Jak dojdzie w całości to obliczone na serwerze przy tworzeniu md5, będzie identyczne z tym, które będzie obliczone u klienta. Jeżeli coś się zgubi to klient może poprosić o powtórne wysłanie obiektu.

0

Opwkowywacza z md5 tez musi wyslac, i wiedziec kiedy doszedl caly a kiedy nie. A probowanie md5 co bajta dla wielu klientow moze tez sie zle skonczyc dla servera, mysle ze to jest bardzo slabe rozwiazanie.
A mozesz np zrobic sobie taki mini protokol, ktory by polegal na tym ze po stronie tego co odbiera masz bufor bajtow ktore odbierasz. Jak dany odbierasz sie budzi i ma nowe dane dostepne z sieci, to je odbiera, i na koniec sprawdzacz czy ten bufor konczy sie jakims tam konkretnym znakiem / ciagiem znakow. Np zalozmy ze bedzie to string END. Teraz mozesz po kazdym nowym odebraniu danych sprawdzic czy 3 ostatnie elementy tablicy to bajty odpowiadajace 'E', 'N' i 'D'. Jelsi tak, to obiekt jest caly, i zdeserializuj go sobie czy co tam chcesz z tego bufora danych, po odcieciu tych ostatnich znacznikow, a jesli nie, to dalej czekasz na nowe dane.
Oczywiscie mozna spytac co jesli normalne dane beda zawierac taki ciag bajtow, moze wtedy sie czytanie za wczesnie skonczyc. Jako ze Ty wiesz co bedziesz wysylac, to mozesz ustalic sobie znacnzik jaki chcesz, wiedzac ze taki ciag bajtow nie wystapi.

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