Reputation: 529
I am trying to connect by a TCP/IP protocol to a program that is not made in Delphi, and I have no documentation on how to do it.
Using a service made in Delphi, I have monitored communication between two clients of the program, and write sendt text to a file, so I can play it back in my Delphi program.
I managed to send several things, but the problem is when I have to give this text:
SOH NUL ÜÜ NUL ENQ NUL Data ENQ NUL NUL NUL SOH NUL NUL NUL NUL 557
I see that there are special characters in string parts, and am having trouble sending these data.
I have tried to send it as a string and put the ASCII values but special characters are not working.
Here is part of my code:
TCPClient := TIdTCPClient.Create(nil);
TCPClient.Host := edtIP.Text;
Memo1.Lines.Clear;
TCPClient.Port := PORT;
TCPClient.ConnectTimeout := 20000;
TCPCliente.Connect;
Memo1.Lines.Add('Conectado con el Sevidor');
TCPClient.Socket.ReadTimeout := 20000;
edtTextoEnvio.Text := edtVersion.Text+' '+edtIP.Text+' '+
edtAlias.Text+' '+edtFuncion.Text+' 'edtPassword.Text;
TCPClient.Socket.WriteLnRFC(edtTextoEnvio.Text, IndyTextEncoding_8Bit);
Memo1.Lines.Add('Mensaje Enviado: '+edtTextoEnvio.Text);
TextoRecibido := TCPCliente.Socket.ReadLn(IndyTextEncoding_8Bit);
Memo1.Lines.Add('Mensaje Recibido: '+TextoRecibido);
TCPCliente.Socket.WriteLnRFC(NUNProc, IndyTextEncoding_8Bit);
Memo1.Lines.Add('Mensaje Enviado: '+NUNProc);
envioMensaje:= Char(1)+ Char(0)+'ÜÜ'+ Char(0)+ Char(5)+Char(0)+'Data'+Char()5)+Char(0)+Char(0)+Char(0)+Char(1)+CHar(0)+Char(0)+Char(0)+Char(0)+'557';
TCPCliente.Socket.WriteLnRFC(envioMensaje, IndyTextEncoding_8Bit); //here is the problem
TextoRecibido := TCPCliente.Socket.ReadLn(IndyTextEncoding_8Bit);
Memo1.Lines.Add('Mensaje Recibido: '+TextoRecibido);
Upvotes: 0
Views: 2850
Reputation: 596527
Some of the string values that you want to send have non-ASCII characters in them, but sockets have no concept of text, only bytes. You have to encode the strings into bytes using an appropriate charset, then you can send the bytes as needed. Indy has functionality built-in to handle that for you (such as the TIdIOHandler.DefStringEncoding
property, and the AByteEncoding
parameter of string-based TIdIOHandler.Write...()
and TIdIOHandler.Read...()
methods). You are trying to take that into account, but you are using the wrong Indy encoding to do it. IndyTextEncoding_8bit
is not really a charset, it is primarily intended as a workaround for dealing with 8bit binary data in text-based protocols, and should not be used in general code. What you need to do instead is identify the actual charset that the other party is expecting you to use. Different charsets encode the same non-ASCII characters in different ways (if at all), so you and the other party must agree on the same charset to encode and decode the strings, otherwise you are going to lose data.
That being said, there are different ways in Indy to accomplish what you are attempting. Given the data you have shown (it would have been better if you had shown the data actually captured by your monitoring service, or better from a packet sniffer like Wireshark), at a minimum I would suggest something more like the following:
TCPClient := TIdTCPClient.Create(nil);
TCPClient.Host := edtIP.Text;
TCPClient.Port := PORT;
TCPClient.ConnectTimeout := 20000;
TCPClient.ReadTimeout := 20000;
Memo1.Lines.Clear;
TCPClient.Connect;
TCPClient.IOHandler.DefStringEncoding := CharsetToEncoding('ISO-8859-1'); // <-- this is just a guess!
Memo1.Lines.Add('Conectado con el Sevidor');
edtTextoEnvio.Text := edtVersion.Text + ' ' + edtIP.Text + ' ' + edtAlias.Text + ' ' + edtFuncion.Text + ' ' + edtPassword.Text;
TCPClient.IOHandler.WriteLn(edtTextoEnvio.Text);
Memo1.Lines.Add('Mensaje Enviado: ' + edtTextoEnvio.Text);
TextoRecibido := TCPClient.IOHandler.ReadLn;
Memo1.Lines.Add('Mensaje Recibido: ' + TextoRecibido);
TCPClient.IOHandler.WriteLn(NUNProc);
Memo1.Lines.Add('Mensaje Enviado: ' + NUNProc);
TCPClient.IOHandler.WriteBufferOpen;
try
TCPClient.IOHandler.Write(Byte(1));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write('ÜÜ');
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(5));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write('Data');
TCPClient.IOHandler.Write(Byte(5));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(1));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write('557');
TCPClient.IOHandler.WriteLn;
TCPClient.IOHandler.WriteBufferClose;
except
TCPClient.IOHandler.WriteBufferCancel;
raise;
end;
TextoRecibido := TCPClient.IOHandler.ReadLn;
Memo1.Lines.Add('Mensaje Recibido: ' + TextoRecibido);
That being said, all of those nul bytes are more likely to be part of multi-byte binary integers, which you can send using TIdIOHandler.Write(Int16)
, TIdIOHandler.Write(Int32)
, etc:
TCPClient.IOHandler.WriteBufferOpen;
try
{
TCPClient.IOHandler.Write(Byte(1));
TCPClient.IOHandler.Write(Byte(0));
}
TCPClient.IOHandler.Write(Int16(1), False);
TCPClient.IOHandler.Write('ÜÜ');
TCPClient.IOHandler.Write(Byte(0));
{
TCPClient.IOHandler.Write(Byte(5));
TCPClient.IOHandler.Write(Byte(0));
}
TCPClient.IOHandler.Write(Int16(5), False);
TCPClient.IOHandler.Write('Data');
{
TCPClient.IOHandler.Write(Byte(5));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
}
TCPClient.IOHandler.Write(Int32(5), False);
{
TCPClient.IOHandler.Write(Byte(1));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write(Byte(0));
}
TCPClient.IOHandler.Write(Int32(1), False);
TCPClient.IOHandler.Write(Byte(0));
TCPClient.IOHandler.Write('557');
TCPClient.IOHandler.WriteLn;
TCPClient.IOHandler.WriteBufferClose;
except
TCPClient.IOHandler.WriteBufferCancel;
raise;
end;
And the ÜÜ
is also very suspicious. It is most likely NOT actually a ÜÜ
string, but more likely just bytes $DC $DC
, 2 8-bit 220
values, a 16-bit 56540
value, etc.
Without clear documentation about the actual communication protocol, you are just making guesses, and you are likely to guess wrong at times. So I strongly suggest you contact the author of the other client app and ask for documentation. Or search online and see if a 3rd party has already written such documentation for that app. Otherwise you are just coding blind, and that is not the good option.
Upvotes: 3