简体   繁体   中英

Read Input from Indy10

I am working with Indy10 in Delphi XE4, and am trying to make a simple TCP connection with a TCP server on the network. The server sends a simple Hello World message, and then disconnects, and waits for another connection. I have the following code, to connect, and to try and read the message from the server.

with Client do
begin
  Host := '10.10.81.122';
  Port := 3490;
  Connect;

    if IOHandler.Connected then
      writeln('Connected!');

    if IOHandler.InputBufferIsEmpty then
    begin
      if  IOHandler.CheckForDataOnSource(1000) then
      begin
        writeln('Buffer size:' + IntToStr(IOHandler.RecvBufferSize));
        IOhandler.ReadBytes(buffer, IOHandler.RecvBufferSize);
      end
      else
        writeln('Message not received');
    end;

end;

When I run this code, I get a value for the recvBufferSize, but the buffer remains empty and then I get a connection terminated gracefully message.

The RecvBufferSize has nothing to do with how many data is actually available for reading. The RecvBufferSize merely specifies the size that Indy uses when allocating internal buffers for reading raw data from the socket. Whatever raw data is actually read gets placed in the IOHandler.InputBuffer for later use by ReadBytes() and other IOHandler reading methods.

Use this code instead:

with Client do
begin
  Host := '10.10.81.122';
  Port := 3490;

  try
    Connect;
    WriteLn('Connected!');

    if IOHandler.CheckForDataOnSource(1000) then
    begin
      WriteLn(Bytes available:' + IntToStr(IOHandler.InputBuffer.Size));
      IOHandler.ReadBytes(buffer, IOHandler.InputBuffer.Size);
    end else
      WriteLn('Message not received');
  except
    on E: Exception do
      WriteLn('Error! ' + E.Message);
  end;
end;

Alternatively:

with Client do
begin
  Host := '10.10.81.122';
  Port := 3490;
  ReadTimeout := 1000;

  try
    Connect;
    WriteLn('Connected!');

    IOHandler.ReadBytes(buffer, -1);
    if Length(buffer) > 0 then
      WriteLn('Bytes read:' + IntToStr(Length(buffer)))
    else
      WriteLn('Message not received');
  except
    on E: Exception do
      WriteLn('Error! ' + E.Message);
  end;
end;

That being said, that is no guaratee that you will actually receive the full message, since this code is merely reading whatever raw data is available at the moment of reading. Since your server is sending a line break at the end of the data, you can use ReadLn() instead of ReadBytes() and let Indy wait until the line break is actually received:

with Client do
begin
  Host := '10.10.81.122';
  Port := 3490;
  ReadTimeout := 1000;

  try
    Connect;
    WriteLn('Connected!');
    Msg := IOHandler.ReadLn;
    if not IOHandler.ReadLnTimedOut then
      WriteLn('Message read:' + Msg)
    else
      WriteLn('Message not received');
  except
    on E: Exception do
      WriteLn('Error! ' + E.Message);
  end;
end;

Alternatively:

with Client do
begin
  Host := '10.10.81.122';
  Port := 3490;

  try
    Connect;
    WriteLn('Connected!');

    Msg := IOHandler.ReadLn(LF, 1000);
    if not IOHandler.ReadLnTimedOut then
      WriteLn('Message read:' + Msg)
    else
      WriteLn('Message not received');
  except
    on E: Exception do
      WriteLn('Error! ' + E.Message);
  end;
end;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM