Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Nov : Re: TIdIOHandler.ReadStream() hangs if I unplug the network cable
| Subject: | Re: TIdIOHandler.ReadStream() hangs if I unplug the network cable |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Thu, 15 Nov 2007 10:14:21 |
"Adrien Reboisson" <adrien-reboisson-at-astase-dot-com@lala.com> wrote in
message news:473c2247@newsgroups.borland.com...
> I unplug the client network connection cable
You shouldn't be doing that in the first place.
> Indy, on the server side does not detect the disconnection
It is not supposed to. You are performing an abnormal disconnection on a
remote machine. The OS on the other end can't detect such a disconnect in a
timely fashion, so Indy doesn't know the socket is gone. The OS has to wait
for the socket to time out internally, which can take HOURS on a Windows
machine.
> and ReadStream() never returns :
Of course not. Indy uses blocking sockets, so until the socket times out
internally, the OS happily continues waiting for more data that will never
arrive. Once the socket times out, then the OS can report errors on it, and
Indy can react to it.
> from my point of view, ReadStream() should raise an exception
It can't until the OS detects the disconnect first and starts reporting
errors for the socket. Then Indy will raise an exception accordingly. But
like I said, that will not happen in a timely manner because of the way
sockets are implemented internally.
> In my case, I want to be notified when such events occurs in
> order to perform some other operations.
Then you will have to set Indy's ReadTimeout property to a value of your own
choosing (it is set to Infinite by default) and then handle any explicit
timeouts that occur, even if a disconnect is not the cause.
> It can also be an Indy or a system timeout
The Indy timeout is controlled by the ReadTimeout property. For the system
timeout, look at the SO_RCVTIMEO flag of the setsockopt() API function.
> So, is it an Indy issue ?
No.
> Or is it by design ?
Yes. Momentary network outages are common on big networks, especially one
as big as the Internet. If a network connection goes down and then comes
back up quickly enough, a socket is designed to attempt to reconnect itself
internally if possible. If sucessful, the application will never know the
connection was interrupted and the socket will continue working. That is
where the internal timeout comes into play, and why the OS can't decide to
invalidate a socket right away.
> What puzzle me more is that when I kill the client application
> WITHOUT unplugging the network cable, all goes well : the
> exception "Socket Error # 10054 Connection reset by peer"
> is raised. What's the difference between the two events ?
The first is hardware-related, whereas the second is software-related. You
can't kill a process without the OS knowing about it. But you can pull out
the cable and the OS might not be watching the hardware close enough to
detect it right away, especially if it is occuring on a different machine.
On the software side, knowing that the process has disappeared, the OS can
invalidate any resources it was using, including sockets. Since the network
connection is still active, that condition can be transmitted to the other
machine right away. That is not the case when you pull out the cable.
Gambit