Sprawdzenie poprawności odpowiedzi klienta TCP

0

Witam

Mam aplikację na zasadzie klient-serwer TCP.
Serwer wysyła odpowiedzi na zapytania klient w postaci określonych bajtów. Np wysyłam zapytanie o status i otrzymuję odpowiedź w postaci 5 bajtów. Każdy z bajtów może przyjmować jedną z określonych wartości. Jak najszybciej i najprościej stworzyć mechanizm sprawdzający poprawność odpowiedzi? Czasem zdarza się że w odpowiedzi wróci jakiś "niedozwolony" bajt - chciałbym się przed tym zabezpieczyć tworząc mechanizm sprawdzający po kolei każdy z bajtów.

0

dodaj bajt kontrolny np CRC8

0

W sensie po stronie serwera żeby wysyłał w odpowiedzi?? Niestety nie mam takiej możliwości - serwer nie leży "po mojej stronie" - ma już gotowy "soft" (urządzenie przemysłowe) i raczej producent nie doda dla mnie takiego udogodnienia.
Po stronie klienta chciałbym sprawdzać.

0

Ogólnie protokół TCP powinien zapewnić bezbłędną transmisję danych, ale skoro twierdzisz, że otrzymujesz niedozwolony bajt to może nie tak parsujesz te odpowiedzi. Urządzenie przemysłowe z którym się komunikujesz powinien mieć protokół transmisji zaprojektowany tak aby wykluczyć takie zjawiska.
Jak wygląda ramka odpowiedzi? Ma znacznik konca transmisji ramki, albo jakis bajt określajacy długość danych w pakiecie/ramce?

0

No i chyba znalazłem błąd w moim kodzie :)
Ogólnie jest to terminal wagowy w którego dokumentacji napisano:
"Rozkaz odczytu rejestru statusu powoduje odesłanie przez wagę ciągu 5 bajtów :

<bajt0> + <kod_klaw1> + <kod_klaw0> + <stan_wejść> + <stan wagi> +00h"
Założyłem więc że odpowiedź będzie miała 5 bajtów a na końcu jest 6 bajt 00h. Z tego powodu odpowiedź się "rozjeżdżała" i znaki się przesuwały. Jak zmieniłem na 6 to jak na razie nie mam błędów w odpowiedzi.

dodanie znacznika <code> - fp

0

generalnie nie do końca ufaj dokumentacji do wag :). Miałem do czynienia z różnymi typami i producentami (min. Radwag, Fawag, Axis, Digi, Mettler Toledo, Rhewa) i nie jest niczym nadzwyczajnym, że dokumentacja swoje a odpowiedź z wagi swoje :). Także jeśli coś jest inaczej niż w dokumentacji a jesteś w stanie uzyskać powtarzalną odpowiedź to po prostu musisz założyć, że dokumentacja jest do np. starszej wersji protokołu

0

Ja właśnie "walczę" z Axis SE-12. Próbuję napisać program który z założenia jest dość prosty ale jestem początkującym programistą więc idzie mi to jak krew z nosa ...

0

Może inaczej - zakładając że bufor na odpowiedz to np byte[256] jak sprawdzić ile bajtów faktycznie odsyła urządzenie jeśli ostatni znak to 00h ??
Jak odciąć zbyteczne "puste" bajty?

0

przecież dostajesz też info ile bajtów odebrano więc w czym problem?

0

abrakadaber, "bawiłeś się" z Axisem - czy miałeś taki problem że np wysyłałeś zapytanie o status a otrzymywałeś odpowiedź w żaden sposób nie pasującą do tego co powinno wrócić ?? Odpowiedź powinna być na zasadzie np FFFFF lub np 10BF3 a tymczasem wraca np OK} . Nie wiem gdzie leży problem - raz działa a raz nie.

0

do SE12 najpierw wysyłasz (bajty w hexie):
02 NumerWagi 0D 7B 80 7D
jeżeli w odpowiedzi dostaniesz jako pierwsze duże w W to znaczy, że waga jest wyłączona guzikiem, tzn. jest włączona do prądu ale w stanie czuwania/uśpienia/czy jak to się tam nazywa. Jak coś innego to można pytać o masę:
02 NumerWagi 0D 7B 87 7D
w odpowiedzi powinieneś dostać

  • pierwszy znak = S - stabilna
  • drugi znak = - - wartość ujemna
  • znaki od 3 do 9 to masa
  • znaki od 10 do 12 to jednostka

jeśli do wagi wysyłasz pytanie o coś to na końcu odpowiedzi jest bajt 00, jeśli do wagi wysyłasz polecenie, np. taruj, to waga odsyła w odpowiedzi (to tylko 3 ostatnie znaki, nie pamiętam co jest z przodu) 'OK}'

Odpowiedź jest odsyłana tekstem jednak bezpieczniej jest wysyłać byte array niż string

0

Właśnie o to chodzi że wysyłając
02 NumerWagi 0D 7B 80 7D powinien dostać 5 bajtów "statusu" wagi i tak jak piszesz jedna z opcji to pierwszy bajt W. Ja akurat chcę uzyskać w pierwszych 3 bajtach 10B czyli kod wprowadzony pod F1 zatwierdzony enterem (wtedy odczytuję co znajduje się pod F1). Zdarza się że zamiast 5 bajtów na zapytanie 02 NumerWagi 0D 7B 80 7D dostaję "OK}".
Miałeś też taki przypadek??
Ja do wagi podłączam się po eth przez Tibbo

0

ja też mam ten moduł podłączony przez tibbo :) ale ja go używam tylko do odczytu masy i ew. tarowania/zerowania z programu. Jednak nie spotkałem się z takim przypadkiem, jaki opisujesz - może dostajesz w buforze poprzednią odpowiedź. Waga nie odpowiada natychmiast po wysłaniu rozkazu a dopiero po chwili. Pokaż kawałek kodu, gdzie masz wysłanie i czekanie na odpowiedź

0
 
byte[] ZapytanieOStatus = KomunikatyWspolne.PoczatekKomunikacji.Concat(OdczytZWagi.Kom_RejestrStatusu).Concat(KomunikatyWspolne.KoniecKumunikacji).ToArray();
            byte[] ZapytanieONrOperatora = KomunikatyWspolne.PoczatekKomunikacji.Concat(OdczytZWagi.Kom_ZatwierdzoneF1).Concat(KomunikatyWspolne.KoniecKumunikacji).ToArray();
            byte[] status = new Byte[6];
            byte[] nroperatora = new Byte[17];
            String status_str = String.Empty;
            String status_str_obciete = String.Empty;
            String nroperatora_str = String.Empty;
            
            WysylkaDoWyswietlaczaWagi_4linie(WysylkaDoWyswietlacza_Komunikaty.LogWitaj, WysylkaDoWyswietlacza_Komunikaty.LogZaloguj, WysylkaDoWyswietlacza_Komunikaty.PustaLinia, WysylkaDoWyswietlacza_Komunikaty.LogNrOperatora);
            NetworkStream stream = KlientTCP.GetStream();
            
            do
            {
                stream.Write(ZapytanieOStatus, 0, ZapytanieOStatus.Length);
                Int32 bajty = stream.Read(status, 0, status.Length);
                status_str = System.Text.Encoding.ASCII.GetString(status, 0, status.Length);
                status_str_obciete = status_str.Substring(0, 3);
            }
            while (status_str_obciete != "10B");
            do
            {
                stream.Write(ZapytanieONrOperatora, 0, ZapytanieONrOperatora.Length);
                Int32 bajty2 = stream.Read(nroperatora, 0, nroperatora.Length);
                nroperatora_str = System.Text.Encoding.ASCII.GetString(nroperatora, 0, nroperatora.Length);
            }
            while (nroperatora_str[0] == 'F');
            int nroper = Convert.ToInt32(nroperatora_str);

// tutaj dalsza część kodu

Masz rację z tym opóźnieniem w odpowiedzi. To faktycznie wygląda jak odpowiedź na wcześniejsze zapytanie. Staram się poprzez do {} while () zabezpieczyć się przed nieprawidłową odpowiedzią.
Generalnie powyżej jest fragment mechanizmu logowania czyli wysyłam tekst do wyświetlacza i czekam aż na terminalu pojawi się kombinacja "F1 nr operatora Enter" czyli "10B" - jak to jest spełnione to pytam o to co wprowadzono pod F1 itd itd

0

tutaj Int32 bajty = stream.Read(status, 0, status.Length); zamiast odczytywać tylko 6 bajtów byte[] status = new Byte[6]; odczytuj np. bufor 1024 bajtów, sprawdzaj ile faktycznie odczytałeś - bajty i pracuj na buforze. Jeśli odczytujesz tylko 6 bajtów to może się zdarzyć, że między kolejnymi odczytami zostaną Ci jakieś śmieci z poprzednich odpowiedzi. Generalnie powinieneś za każdym razem odczytać wszystko co jest w buforze i odpowiednio to interpretować wtedy nie będziesz miał takich problemów

0

Zmieniłem - dałem że ma być 1024 (wcześniej miałem 256 zanim zmieniłem na to co wg specyfikacji powinno wrócić)
W odpowiedzi dostałem

 status_str "10B3F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 

:)))
Po zrobieniu Substring(0, 3) jest ok.
Poszło więc zapytanie o nr operatora (to co wprowadzono pod F1) i w odpowiedzi mamy nroperatora_str "1\0FFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
Początek się zgadza bo było wprowadzone 1, potem faktycznie są jakieś śmieci "FFF" a później "pustka" do końca buforu. Problem polega na tym że robię tutaj konwersję do int i program się wysypuje bo takiego string nie jest w stanie przekonwertować. Pytanie jak są traktowane te "puste" bajty? Jak "obciąć" tylko to co potrzebne czyli tak na prawdę 1 w tym przypadku? Za jeden poza pustym bajtem mamy jeszcze śmieci "FFF"...

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