Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Mar : Re: How to check TIdPeerThread.Connection for input characters?
| Subject: | Re: How to check TIdPeerThread.Connection for input characters? |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Thu, 15 Mar 2007 12:15:17 |
"Mark" <mkhuebner@gmail.com> wrote in message
news:1173985177.769914.208410@p15g2000hsd.googlegroups.com...
> I was hoping there would be a property that I could
> read that would tell me if there is another message
That is not how TCP works. It is an arbitrary byte stream. It has
no concept of "messages". That is a higher-level concept in the
application's own code. The socket only ares about the flow of bytes,
but not what the bytes actually represent. That application code has
to process that aoccordingly.
There are two ways to know if there are any pending bytes on the
socket, regardless of whether the bytes belong to a message that is
still in the process of being received, or if they belong to a
completely new message:
1) call the WinSock API ioctlsocket() function directly, specifying
the FIONREAD command, to determine how many bytes can be read from the
socket atomically without blocking the socket.
2) call the connection's ReadFromStack() method with a short timeout,
even 0. It will return how many pending bytes, if any, were received
from the socket into the connection's InputBuffer property.
What EXACTLY are you trying to receive from the clients? Please
provide more details.
> I'm currently using ReadLn(ETX) so it will stop reading when
> it detects an ETX character.
Then you don't need to bother with detecting pending bytes. Each
message has an explicit terminator to it. Calling ReadLn(ETC) will
keep reading until that terminator is received. At which point, you
are already at the end of the message, and can decide whether to
disconnect at that time, or to wait for the next message.
> Does the IdTCPServerExecute(AThread: TIdPeerThread) event
> fire when the first character of a message arrives or after the last
> character arrives or at some other time?
The OnExecute event is triggered in a loop for the lifetime of the
connection. It has no ties to the data whatsoever. As soon as the
client connects, OnExecute begins triggering as soon as the OnConnect
event handler exits. When the OnExecute event handler exits, it is
triggered again immediately if the connection is still open. It is
the responsibility of the code inside the event handler to read and
process the data as needed.
Which is why you shouldn't really be bothering with trying to detect
pending bytes. Just read a message whenever the event is triggered,
and then close the connection is needed. The next time the event is
triggered, you can read another message. Since you are using
ReadLn(), you can use the ReadLnTimedOut property to know if ReadLn()
returned anything useful. If no message arrived, then you can close
the socket. For example:
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
Msg: String;
begin
Msg := AThread.Connection.ReadLn(ETX, 30000);
if AThread.Connection.ReadLnTimedOut then
begin
AThread.Connection.DisconnectSocket;
Exit;
end;
// process Msg as needed...
end;
> Should I close it if a message is ACK'ed?
Liike I said earlier, I do not recommend tearing down a connection
unnecessarily. There is a lot of overhead in establishing a socket
connection. The more you can reuse a connection, the better
performance you will have between that client and the server.
Gambit
none