Mam bardzo dziwne zachowanie podczas pisania do gniazda. W moim telefonie klienta używam gniazdo, które jest zainicjowany w następujący sposób:OutputStream.write() się powiodło, ale dane nie zostały dostarczone
private void initSocket()
{
socket = new Socket();
socket.connect(new InetSocketAddress(host, port));
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
}
następnie okresowo (co 60 sekund) I czytać i pisać jakieś dane do tego gniazda (kod tutaj jest trochę uproszczona) :
if(!isSocketInitialized())
{
initSocket();
}
byte[] msg = getMessage();
os.write(msg);
os.flush();
int bytesAvailable = is.available();
if(bytesAvailable>0)
{
byte[] inputBuffer = new byte[bytesAvailable];
int numRead = is.read(inputBuffer, 0, bytesAvailable);
processServerReply(inputBuffer, numRead);
}
I działa. Ale ... Czasami (bardzo rzadko, może 1 lub 2 razy dziennie) mój serwer nie otrzymuje danych. Mój dziennik klienta wygląda następująco:
Written A
Written B
Written C
Written D
Written E
i tak dalej. Ale po stronie serwera to wygląda:
Received A
Received E
B, C, D rekordów danych nie zostały otrzymane, pomimo faktu, że po stronie klienta wygląda wszystkich danych została wysłana bez żadnych wyjątków!
Takie luki mogą być małe (2-3 minuty), co nie jest złe, ale czasami mogą być bardzo duże (1-2 godziny = 60-120 cykli) i jest to naprawdę problem dla moich klientów.
Naprawdę nie mam pojęcia, co może być nie tak. Dane wydają się być wysyłane przez klienta, ale nigdy nie docierają do serwera. Sprawdziłem to również z proxy.
Mam tylko dzienniki i nie mogę odtworzyć tego problemu (ale zdarza się to mojemu klientowi więcej niż jeden raz każdego dnia), aw dziennikach czasami widzę, że połączenie jest zerwane przez wyjątek "sendto failed: ECONNRESET (Połączenie resetowane przez peer) ". Następnie program zamyka gniazdo, ponownie inicjuje:
// close
is.close();
os.close();
socket.close();
// reinitialize
initSocket();
i próbuje ponownie zapisać dane zgodnie z powyższym opisem. Wtedy widzę problem: nawiązanie połączenia, pomyślne pisanie, ale na serwerze nie ma DANYCH!
Może to mieć coś wspólnego z ECONNRESET, może nie być, ale chcę o tym wspomnieć, ponieważ może być to ważne.
Byłbym bardzo wdzięczny za wszelkie pomysły i wskazówki.
P.S. Może to odgrywa pewną rolę: kod klienta działa na urządzeniu mobilnym z Androidem, które się porusza (jest w samochodzie). Połączenie internetowe jest ustanawiane przez GPRS.
UPD: Potrafię to odtworzyć! Przynajmniej częściowo (klient wysyła A, B, C, D, E, a serwer otrzymuje tylko A). Zdarza się, za każdym razem, gdy:
nawiązaniu połączenia, klient czyta i pisze -> OK
połączenie zostanie przerwane (wyłączyć router WLAN :)), stałem IOException, Zamykam strumienie i gniazdo -> OK
Włączam router, połączenie się z powrotem, uruchamiam ponownie gniazdo, program wykonuje write() bez wyjątków, ale ... żadne dane nie docierają do serwera .
BTW ponieważ połączenie jest ponownie dostępny() zwraca zawsze 0.
Jedną z rzeczy, które mogą pomóc, jest posiadanie serwera, który mógłby próbować zsynchronizować się z urządzeniem. Jeśli za pierwszym razem pominie dane, zawsze może spróbować ponownie - w zależności od tego, jak często sondujesz dane. – Max
@max, jasne, masz rację. Ale serwer jest zamkniętym oprogramowaniem i nie mogę zmienić protokołu. – Valelik
Nie można użyć 'ByteArrayOutputStream'? Coś [jak to] (http://stackoverflow.com/a/2984550/1134705) – jnthnjns