我正在尝试设置一个非常基本的单个客户端/服务器系统,因此我可以从我的PC发送一个字符串到Android平板电脑。平板电脑对字符串执行某些操作,然后将字符串发送回PC。代码:
procedure TForm1.Button1Click(Sender: TObject); // start the server
begin
IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('xxx.xxx.x.x', 4405); // for the xxx's the IP adres of the tablet
IdTCPServer1.Active := True;
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var s:string;
begin
s := AContext.Connection.IOHandler.ReadLn();
Try
... do something with the string
AContext.Connection.IOHandler.Writeln('ready');
Except
AContext.Connection.IOHandler.Writeln('Error');
End;
AContext.Connection.Disconnect;
end;
procedure TFMain.FormCreate(Sender: TObject);
begin
IdTCPClient1.host := 'xxx.xxx.x.x'; // xxx's the IP address of the tablet
IdTCPClient1.Port := 4405;
end;
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
begin
s := 'some string';
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.Writeln(s);
if IdTCPClient1.IOHandler.ReadLn='ready' then Button1.text := 'ready'
else Button1.text := 'failed';
IdTCPClient1.Disconnect;
end;
在本地主机或家庭网络中的两台不同PC上运行时,程序运行正常。但是,在平板电脑上安装服务器端时,单击桌面上的button1将导致“连接正常关闭”。这真的很令人沮丧,因为它在两台PC上运行正常,但在PC机上没有安卓平板电脑。我在互联网上搜索了很长时间,也许它与字符串结尾的差异有关,或者(XE5的实现)Android中的线程可能也存在问题。任何有关如何运行上述代码或以不同方式(通过IP)使用XE5在PC和平板电脑之间进行通信的帮助都非常受欢迎。
杰拉德
稍后添加: 通过wireshark,我试图查看正在发送的信息。当在两个表现正常的桌面之间运行时,我得到的通信我假设以下内容适用于手头的程序(server = 192.168.2.11,client = 192.168.2.10)。
197 9.209090000 192.168.2.10 192.168.2.11 TCP 66 56699 > ds-admin [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
198 9.212694000 192.168.2.11 192.168.2.10 TCP 66 ds-admin > 56699 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
199 9.212764000 192.168.2.10 192.168.2.11 TCP 54 56699 > ds-admin [ACK] Seq=1 Ack=1 Win=65536 Len=0
200 9.213041000 192.168.2.10 192.168.2.11 TCP 111 56699 > ds-admin [PSH, ACK] Seq=1 Ack=1 Win=65536 Len=57
201 9.217302000 192.168.2.11 192.168.2.10 TCP 119 ds-admin > 56699 [PSH, ACK] Seq=1 Ack=58 Win=65536 Len=65
202 9.217304000 192.168.2.11 192.168.2.10 TCP 60 ds-admin > 56699 [FIN, ACK] Seq=66 Ack=58 Win=65536 Len=0
203 9.217349000 192.168.2.10 192.168.2.11 TCP 54 56699 > ds-admin [ACK] Seq=58 Ack=67 Win=65536 Len=0
204 9.217543000 192.168.2.10 192.168.2.11 TCP 54 56699 > ds-admin [FIN, ACK] Seq=58 Ack=67 Win=65536 Len=0
207 9.225011000 192.168.2.11 192.168.2.10 TCP 60 ds-admin > 56699 [ACK] Seq=67 Ack=59 Win=65536 Len=0
另一方面,当使用Android平板电脑作为服务器做同样的事情时,我得到以下内容(服务器= 192.168.2.8,客户端= 192.168.2.10):
116 4.792467000 192.168.2.10 192.168.2.8 TCP 66 56407 > ds-admin [SYN] Seq=0 Win=8192 Len=0 MSS=1460 WS=256 SACK_PERM=1
117 4.802487000 192.168.2.8 192.168.2.10 TCP 66 ds-admin > 56407 [SYN, ACK] Seq=0 Ack=1 Win=14600 Len=0 MSS=1460 SACK_PERM=1 WS=64
118 4.802571000 192.168.2.10 192.168.2.8 TCP 54 56407 > ds-admin [ACK] Seq=1 Ack=1 Win=65536 Len=0
119 4.802857000 192.168.2.10 192.168.2.8 TCP 111 56407 > ds-admin [PSH, ACK] Seq=1 Ack=1 Win=65536 Len=57
120 4.808816000 192.168.2.8 192.168.2.10 TCP 60 ds-admin > 56407 [FIN, ACK] Seq=1 Ack=1 Win=14656 Len=0
121 4.808860000 192.168.2.10 192.168.2.8 TCP 54 56407 > ds-admin [ACK] Seq=58 Ack=2 Win=65536 Len=0
122 4.808944000 192.168.2.10 192.168.2.8 TCP 54 56407 > ds-admin [FIN, ACK] Seq=58 Ack=2 Win=65536 Len=0
123 4.812517000 192.168.2.8 192.168.2.10 TCP 60 ds-admin > 56407 [ACK] Seq=2 Ack=58 Win=14656 Len=0
124 4.813608000 192.168.2.8 192.168.2.10 TCP 60 ds-admin > 56407 [RST, ACK] Seq=2 Ack=58 Win=14656 Len=0
125 4.813609000 192.168.2.8 192.168.2.10 TCP 60 ds-admin > 56407 [RST] Seq=2 Win=0 Len=0
126 4.814570000 192.168.2.8 192.168.2.10 TCP 60 ds-admin > 56407 [RST] Seq=2 Win=0 Len=0
这是我第一次看到这种信息,但似乎在工作桌面 - 桌面情况下,行200对应于客户端命令IdTCPClient1.IOHandler.Writeln(s),而行201对应于服务器命令AContext .Connection.IOHandler.Writeln(...)。在桌面平板电脑配置中,客户端将字符串发送到服务器(第119行),但没有[PSH,ACK]返回。相反,有一个[FIN,ACK]响应。这似乎表明Android中的服务器端语句出了问题:s:= AContext.Connection.IOHandler.ReadLn();任何想法可能是什么以及如何解决它?
稍后再添加:在该行周围添加try / except语句 s:= AContext.Connection.IOHandler.ReadLn(); 然后引发异常“连接正常关闭”的异常。当调试delphi说:Project test.apk引发异常类分段错误(11)并转到单元IdIOHandler rev 1.123(2/8/05)中的以下函数。
function TIdIOHandler.ReadLn(AByteEncoding: IIdTextEncoding = nil
{$IFDEF STRING_IS_ANSI}; ADestEncoding: IIdTextEncoding = nil{$ENDIF}
): string;
{$IFDEF USE_CLASSINLINE}inline;{$ENDIF}
begin
Result := ReadLn(LF, IdTimeoutDefault, -1, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ADestEncoding{$ENDIF}
);
end;
那一刻的召唤堆是(第一个项目前面有一个箭头,剩下一个蓝色的子弹,除了最后3个项目,前面有一个灰色的子弹):
Idiohandler.TIdIOHandler.ReadLn(0x797e8cb4,nil,nil)
Umaintablet.TFCalibration_tablet_side.IdTCPServer1Execute(0x74124e70,0x769d76a0)
Idcustomtcpserver.TIdCustomTCPServer.DoExecute(0x76414480,0x769d76a0)
Idcontext.TIdContext.Run(0x769d76a0)
Idtask.TIdTask.DoRun(0x769d76a0)
Idthread.TIdThreadWithTask.Run(0x766bd258)
Idthread.TIdThread.Execute(0x766bd258)
System.Classes.ThreadProc(0x766bd258)
System.ThreadWrapper(0x766bd300)
:4003F3DC __thread_entry
:4003EAC8 pthread_create
:00000000 ??
答案 0 :(得分:0)
对于只需要单个客户端的特定问题,TidSimpleServer对象而不是TidTCPserver对象在我的Android上可以正常工作。