TCP套接字 - 发送控制字符

时间:2015-03-05 16:46:48

标签: sockets delphi delphi-xe7

我正在尝试通过TCP / IP协议连接到Delphi中没有的程序,而且我没有关于如何执行此操作的文档。

使用Delphi中的服务,我监视程序的两个客户端之间的通信,并将sendt文本写入文件,所以我可以在我的Delphi程序中播放它。

我设法发送了几件事,但问题是当我必须提供这个文本时:

SOH NUL ÜÜ NUL ENQ NUL Data ENQ NUL NUL NUL SOH NUL NUL NUL NUL 557

我发现字符串部分中有特殊字符,并且无法发送这些数据。

我尝试将其作为字符串发送并输入ASCII值,但特殊字符不起作用。

以下是我的代码的一部分:

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);

1 个答案:

答案 0 :(得分:3)

您要发送的某些字符串值中包含非ASCII字符,但套接字没有文本概念,只有字节。您必须使用适当的字符集将字符串编码为字节,然后您可以根据需要发送字节。 Indy具有内置功能,可以为您处理(例如TIdIOHandler.DefStringEncoding属性,以及基于字符串的AByteEncodingTIdIOHandler.Write...()方法的TIdIOHandler.Read...()参数。您正在尝试考虑这一点,但您使用错误的Indy编码来执行此操作。 IndyTextEncoding_8bit并不是真正的字符集,它主要用于处理基于文本的协议中的8位二进制数据,而不应用于通用代码。您需要做的是确定另一方期望您使用的实际字符集。不同的字符集以不同的方式编码相同的非ASCII字符(如果有的话),因此您和另一方必须就相同的字符集达成一致,以对字符串进行编码和解码,否则您将丢失数据。

话虽如此,Indy有不同的方式来完成你的尝试。鉴于您已经显示的数据(如果您显示监控服务实际捕获的数据会更好,或者更好地从Wireshark这样的数据包嗅探器中获取),至少我会建议更类似于以下内容:

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);

话虽这么说,所有这些nul字节更可能是多字节二进制整数的一部分,你可以使用TIdIOHandler.Write(Int16)TIdIOHandler.Write(Int32)等发送:

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;

ÜÜ也非常可疑。它很可能实际上不是ÜÜ字符串,更可能只是字节$DC $DC,2个8位220值,16位56540值等。< / p>

如果没有关于实际通信协议的明确文档,您只是在猜测,有时您可能会猜错。所以我强烈建议您联系其他客户端应用程序的作者并索取文档。或者在线搜索并查看第三方是否已经为该应用编写了此类文档。否则你只是盲目编码,这不是一个好的选择。