2

私はPythonでこのコードスニペットを持っています:

s = socket.create_connection(('192.168.0.111', 123), timeout=2.0)
s.sendall('REQUEST,status,interface'); result = s.recv(1024)

IndyコンポーネントのTIdTCPClientを使用してDelphiで「s.recv(1024)」を実行するにはどうすればよいですか?サーバーはターミネータのない文字列を返すため、ReadLnは機能しません。

4

1 に答える 1

4

In Python, recv(1024) simply reads whatever is available on the socket, up to 1024 bytes max. It is possible to do the same thing with TIdTCPClient (see below), but it is not the best way to handle socket programming in general. You really need to know how the server is actually terminating the data. Does it close its end of the connection after sending the data? If not, does it expect you to simply read whatever bytes are available regardless of the actual length? And if so, how does it expect you to handle TCP packet fragmentation (TCP/IP can separate transmitted data into multiple packets, and may receive data as multiple packets even if they were not sent as such)? Does it expect you to keep reading until some timeout occurs, indicating no more data is being sent?

It makes a big difference in how you write code to handle the reading properly. For example:

IdTCPClient1.Host := '192.168.0.111';
IdTCPClient1.Port := 123;
IdTCPClient1.ConnectTimeout := 2000;
IdTCPClient1.Connect;
try
  IdTCPClient1.IOHandler.Write('REQUEST, status, interface');

  // wait for a disconnect then return everything that was received
  Result := IdTCPClient1.IOHandler.AllData;
finally
  IdTCPClient1.Disconnect;
end;

Vs:

IdTCPClient1.Host := '192.168.0.111';
IdTCPClient1.Port := 123;
IdTCPClient1.ConnectTimeout := 2000;
IdTCPClient1.Connect;
try
  IdTCPClient1.IOHandler.Write('REQUEST, status, interface');

  // set the max number of bytes to read at one time
  IdTCPClient1.IOHandler.RecvBufferSize := 1024;

  // read whatever is currently in the socket's receive buffer, up to RecvBufferSize number of bytes
  IdTCPClient1.IOHandler.CheckForDataOnSource;

  // return whatever was actually read
  Result := IdTCPClient1.IOHandler.InputBufferAsString;
finally
  IdTCPClient1.Disconnect;
end;

Vs:

IdTCPClient1.Host := '192.168.0.111';
IdTCPClient1.Port := 123;
IdTCPClient1.ConnectTimeout := 2000;
IdTCPClient1.Connect;
try
  IdTCPClient1.IOHandler.Write('REQUEST, status, interface');

  // keep reading until 5s of idleness elapses
  repeat until not IdTCPClient1.IOHandler.CheckForDataOnSource(5000);

  // return whatever was actually read
  Result := IdTCPClient1.IOHandler.InputBufferAsString;
finally
  IdTCPClient1.Disconnect;
end;
于 2013-01-11T02:31:16.560 に答える