I am trying to setup a very basic single client/server system, so I can send from my PC a string to an android tablet. The tablet does something with the string and then sends back a string to the PC. The code:
server side (tablet)
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;
Client side: (desktop)
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;
The programs run fine when run on localhost or on two different PCs in the home network. However, when installing the server side on the tablet, clicking button1 on the desktop will result in a 'connection closed gracefully'. It is really frustrating, since it does work normal on two PCs, but not on PC to android tablet. I searched a long time on the internet and maybe it has to do with a difference in string endings or there might also be a problem with threads in (XE5's implementation in) Android. Any help on how to get the above code running or a different way (through IP) to communicate between a PC and a tablet using XE5 is highly appreciated.
Gerard
Added later: With wireshark I tried to check what information is being send. When running between two desktops, which behaves normally, I get communication of which I assume the following applies to the programs at hand (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
On the other hand when doing the same thing with the android tablet as a server, I get the following (server=192.168.2.8, client=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
This is the first time I see this kind of information, but it seems that in the working desktop-desktop situation line 200 corresponds to the client command IdTCPClient1.IOHandler.Writeln(s) and line 201 corresponds to the server command AContext.Connection.IOHandler.Writeln(...). In the desktop-tablet configuration the client sends the string to the server (line 119), but there is no [PSH, ACK] back. Instead there is a [FIN, ACK] response. This seems to point to something going wrong in the server-side statement in Android: s := AContext.Connection.IOHandler.ReadLn(); Any ideas what this could be and how to fix it?
Added later again: When putting a try/except statement around the line s := AContext.Connection.IOHandler.ReadLn(); then the exception 'Connection closed gracefully' is raised. When debugging delphi says: Project test.apk raised exception class segmentation fault (11) and goes to the following function in the unit 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;
The Call Stack at that moment is (first item has an arrow in front, rest a blue bullet, except the last 3 items, which have a gray bullet in front):
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 ??