CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - TCPClient Indy i unsigned char
Strona 1 z 2

TCPClient Indy i unsigned char

Nowy postNapisane: wtorek, 18 lutego 2014, 09:47
przez deus100
Witam serdecznie wszystkich na forum.
Staram się wysłać tablicę znaków poprzez TCP Indy w postaci:

KOD cpp:     UKRYJ  
char dane[7];

dane[0]=0x21;
dane[1]=0x89;
dane[2]=0x01;
dane[3]=0x49;
dane[4]=0x50;
dane[5]=0x36;
dane[6]=0x0A;

IdTCPClient1->Socket->Write(dane);

Wszystko było by OK, lecz zamiast 0x89 wysyła mi "3F" (? w ASCII). Ogólnie wszystko powyżej dec 128 wysyła jako 3F. Rozwiązaniem byłoby zadeklarowanie unsigned char zamiast char, ale TCPClient nie chce wysyłać unsigned. Jak mogę w prosty sposób rozwiązać ten problem?
Dzięki wielkie za wszelką pomoc.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: wtorek, 18 lutego 2014, 10:22
przez polymorphism
Zgaduje, że Write służy do wysyłania tekstu a nie danych binarnych, być może następuje jakaś konwersja przed wysłaniem i stąd te przekłamania. Użyj jakiejś metody do wysyłania/odbierania danych binarnych (nie powiem Ci jaka, bo nie mam dokumentacji INDY).


KOD cpp:     UKRYJ  
char dane[7] = { 0x21, 0x89, 0x01, 0x49, 0x50, 0x36, 0x0A };

Tak chyba prościej i czytelniej, prawda?

Re: TCPClient Indy i unsigned char

Nowy postNapisane: wtorek, 18 lutego 2014, 10:29
przez deus100
Można też przez Write wysłać unsigned char, ale jako pojedynczy znak (i wychodzi na sieć dobrze, czyli 0x89), a nie tablicę. Jeśli przekonwertuje to do string (0x89 to znak promila) i wyślę poprzez Write także wysyła 0x3F.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: wtorek, 18 lutego 2014, 10:56
przez polymorphism
Wysyłając pojedynczy znak, używasz innego wariantu metody Write do wysyłania pojedynczego bajta/8-bitowej wartości liczbowej, dlatego to działa. Jeszcze raz napiszę: jak chcesz wysłać dane binarne, użyj odpowiednich do tego celu metod (według dokumentacji jest wersja Write, która przyjmuje parametr typu TIdBytes (alias System.SysUtils.TBytes), może z tym typem zadziała).

Re: TCPClient Indy i unsigned char

Nowy postNapisane: wtorek, 18 lutego 2014, 11:29
przez Cyfrowy Baron
deus100 napisał(a):Jeśli przekonwertuje to do string (0x89 to znak promila)


Znak promila (°) to znak Unicode. Konwertujesz na String - jeżeli używasz starszej wersji środowiska niż C++Builder 2010, to String = AnsiString, więc AnsiString nie przechowa znaku unicode. char też w zasadzie nie powinien obsługiwać unicode. W nowszych wersjach środowiska jest wchar_t dla UnicodeString.

Poza tym write obsługuje więcej typów:

write.png

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 09:25
przez deus100
BCB 6, INDY 10. Gdy korzystam z UDPClient to spokojnie char pomieści wszystkie wartości do 255 i bez marudzenia wysyła całą tablicę. Program Hercules przez TCP i zaznaczonych hexach też wysyła poprawnie. Jak to mogę jeszcze przepchnąć przez inne parametry Write?

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 12:21
przez Cyfrowy Baron
Nie wiem. BCB 6 to przestarzałe środowisko. Pisałeś, że konwertujesz char na String - po co? Sprawdź czy przejdzie char bez konwersji.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 13:17
przez deus100
W BCB 6 mam bardzo rozległy program napisany i nie mogę zmienić, a to ma być dodatek do niego. Konwertowałem do Stringa tylko jako sprawdzenie. Char jako jeden znak oraz tablice wysyła wszystko powyżej 0x80 jako 0x3F. Unsigneg char jeden znak wysyła dobrze, ale Write już nie potrafi wysłać tablicy unsigned. :( a muszę wysłać te znaki jeden po drugim zaraz po innych komendach sterujących.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 15:16
przez Mironas
A musi być TCP? Ja kiedyś testowałem coś podobnego w UDP i działało poprawnie.

Wysyłanie:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  char ch[3] = {56, 129, 200};
  String dane = ch;
  IdUDPClient1->Active = true;
  IdUDPClient1->Send(dane);
  IdUDPClient1->Active = false;
}
 


Odbieranie:
KOD cpp:     UKRYJ  
void __fastcall TForm1::IdUDPServer1UDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)
{
  AnsiString s;
  char buff[3];

  AData->Read(buff, 3);
  s = buff;
  s.SetLength(3);
  //ListBox1->Items->Add(s);

  // kody znakow
  byte kod;
  String wiersz = s + "  ";
  for (int i=0 ; i<s.Length() ; i++)
  {
    kod = buff[i];
    wiersz = wiersz + "{"+IntToStr(kod)+"} ";
  }
  ListBox1->Items->Add(wiersz);
}
//---------------------------------------------------------------------------
 

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 15:57
przez deus100
Niestety musi być TCP (handshake itp). Z UDP mam inną transmisję i działa jak już pisałem dobrze. Znalazłem coś takiego:
IdTCPClient1->Socket->Write(dane, TIdTextEncoding_UTF8); // dodaje kilka znaków zamiast 0x89
IdTCPClient1->Socket->Write(dane, TIdTextEncoding_UTF8, TIdTextEncoding_Default); // jak wyżej
IdTCPClient1->Socket->Write(dane, TIdTextEncoding_Default, TIdTextEncoding_UTF8); // nie zmienia nic
Znacie jakieś inne kodowania?

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 16:21
przez Mironas
Podeślij przykład jak wysyłasz i jak odbierasz.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 20:11
przez polymorphism
Mironas napisał(a):
KOD cpp:     UKRYJ  
  char ch[3] = {56, 129, 200};
String dane = ch;

To jest źle. ch nie jest poprawnym c-stringiem - brak zera na końcu. Działa przez przypadek. Tak ma być:
KOD cpp:     UKRYJ  
 char ch[4] = { 56, 129, 200, 0 };

Re: TCPClient Indy i unsigned char

Nowy postNapisane: środa, 19 lutego 2014, 23:56
przez Cyfrowy Baron
polymorphism napisał(a):
KOD cpp:     UKRYJ  
char ch[4] = { 56, 129, 200, 0 };


Nie twierdzę, że to źle, ale wydaje mi się, że wystarczy tak:

KOD cpp:     UKRYJ  
char ch[4] = { 56, 129, 200};


Znak końca zostanie dodany automatycznie.




Co do problemu, podaj kompletny kod, bym mógł go przetestować na swoim środowisku.

Re: TCPClient Indy i unsigned char

Nowy postNapisane: czwartek, 20 lutego 2014, 10:33
przez polymorphism
(...) ale wydaje mi się, że wystarczy tak: (...)

Może być i tak, choć wydaje mi się, że jawne wstawienie zera jest czytelniejsze, bo pokazuje, "co autor miał na myśli".



Może niech deus100 wyjaśni, co chce wysłać. Dane binarne czy jakiś łańcuch znakowy? Z pierwszego postu wynikało, że opcja pierwsza wchodzi w grę, ale teraz widzę, że chodzi o tekst. Więc w końcu jak jest?

Re: TCPClient Indy i unsigned char

Nowy postNapisane: czwartek, 20 lutego 2014, 14:31
przez deus100
Nie wiem co tego stringa się uczepiliście :) Chodziło o dane wysyłane w czystej postaci hex. Dziękuję za zainteresowanie kolegów, ale sprawa rozwiązana. Chodziło o sposób kodowania znaków przez INDY.
Dla potomnych:

KOD cpp:     UKRYJ  
char dane[7];
// <- tutaj zapisujemy tablice w jaki sposób nam się podoba
IdTCPClient1->Socket->Write(dane, TIdTextEncoding_Default);


Jeszcze raz dzięki za zainteresowanie i pomoc.