Connection Closed Gracefully when IdTCPClient.IOHandler.ReadStream()!

I'm new to delphi and this is my first project. Here's a little bit of code:

procedure TForm1.Button2Click(Sender: TObject);
responseStringFromServer:TStringStream;
begin
 try
  if IdTCPClient1.Connected then
   begin
    dataSentToDevice:= 'http/1.0 content-length: 344 content-type: text/xml <?xml          version="1.0" encoding="UTF-8" ?> ...'
   IdTCPClient1.IOHandler.WriteLn(dataSentToDevice);
   responseStringFromServer := TStringStream.Create;
    IdTCPClient1.IOHandler.ReadStream(responseStringFromServer);
    ...

I have a device connected to local network. I manage to connect to it succesfully. Sending commands is working too, but when i do

IdTCPClient1.IOHandler.ReadStream(responseStringFromServer);

then it waits til device is done processing and an exception occurs: "Connection Closed Gracefully". So i'm not able to read data the device is supposed to send me. Device is not shutting down. I've read other posts and i understand that device itself drops connection.

I have a demo program that communicates with it and it works fine. I need to get response xml before it drops the connection.

Also the request is http and i am using IdTCPClient (i need to use xml request, i don't know how to do it with TidHTTP). May it be that after device is sending response it drops the connection, so that my tcpclient gets connection dropped flag before receiving data.

Any help would be appreciated!


Also the request is http and i am using IdTCPClient (i need to use xml request, i don't know how to do it with TidHTTP).

Working with IdHTTP is simple...

  • Drop an instance of it on your form, select it.
  • In Object Inspector, go to ProtocolVersion property, and set it to pv1_0, then open its
  • Request property set, and set Request.ContentType to text/xml, and Request.ContentEncoding to UTF-8, and set other properties if required.
  • Add a button to your form and double-click on it.
  • In your code, create an instance of TStringStream, and load your XML content into it.
  • Assign your stream to IdHttp.Request.Source.
  • Call IdHttp.Get() method by giving it a host address.
  • IdHttp.Get() returns a string which is the response the server sent you.

  • The way you are calling ReadStream(), it will interpret the first 4 bytes (or 8 bytes if the TIdIOHandler.LargeStream property is True) as an Integer (or Int64) in network-byte order that specifies the length of the data, and then it will try to read that many bytes. Is the device actually sending such a length value? If not, then ReadStream() will attempt to read the wrong number of bytes. An EIdConnClosedGracefully exception means the device is closing the socket on its end. So either the device is closing the connection immediately after sending its data, or it is timing out waiting for you to send the next command, which you cannot do since you are blocked waiting for the wrong data from the previous command.


    As said by @Remy Lebeau and the documentation (press F1 when your edit caret is over the ReadStream sentence):

    AByteCount indicates the number of bytes from the IOHandler to be read into AStream . When AByteCount contains -1 and AReadUntilDisconnect contains False, the byte count is read as an Integer value from the IOHandler . The size of AStream is adjusted to match the size expected from the IOHandler.

    This is very useful when you're connecting to servers written also in INDY WriteStream in one end, ReadStream in the other, or any other language if you send that byte cound as expected by INDY client.

    If you're reading from a device, be sure the device is sending that info up-front the stream or change the way you read the data. If you know the size of the stream, just pass the second parameter: AByteCount. If the device will close the channel when the stream ends, pass -1 as the second parameter and True as the third parameter: AReadUntilDisconnect.

    If the device send text of unknown length but using a known terminator (like CR/LF), you better use ReadLn method of IOHandler to get that string.

    Take a look at if neither fits your needs, take a look on Read* methods of TIOHandlerClass and RTFM for each to find the correct one to get the data sent by the device.

    链接地址: http://www.djcxy.com/p/76468.html

    上一篇: 如何处理TCPClient中接收到的数据? (德尔福

    下一篇: 当IdTCPClient.IOHandler.ReadStream()时,连接正常关闭!