Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Answer: How do i detect that the client has disconnected ? (i'm using sysread/write)

by Zombie shlomi (Initiate)
on Oct 03, 2001 at 01:00 UTC ( #116271=categorized answer: print w/replies, xml ) Need Help??

Q&A > network programming > How do i detect that the client has disconnected ? (i'm using sysread/write) - Answer contributed by Zombie shlomi

Hello Paul, Thank you for the reply . I did some more reading about syswrite in perldoc but there's nothing about returning errors except the undef value (EAGAIN??). I don't want to use "IO::Whatever" , I want to do this using only low level functions. My goal is a low level server, non-blocking, non-forking ,multiple connections ... its working , but i have this problem with the detection of disconnected sockets. can you please give me a short example of using getpeername for detection ? thanks, Shlomi

  • Comment on Answer: How do i detect that the client has disconnected ? (i'm using sysread/write)
Replies are listed 'Best First'.
Re: Answer: How do i detect that the client has disconnected ? (i'm using sysread/write)
by pjf (Curate) on Oct 03, 2001 at 03:48 UTC
    Ah, EAGAIN and related issues will make more sense if you understand the underlying system calls, in this case write(2). There are a bunch of reasons a write can fail, and the EAGAIN error status indicates that the other end of the connection was not ready to receive input, which is almost always caused by a big queue of data which the receiving process simply hasn't looked at yet.

    If syswrite returns undef, it will place the reason it returned undef into $!, which if evaluated numerically will yield the current value of the C "errno" variable. You can test for particulr errors explicitly like this:

    use POSIX qw/EAGAIN EFBIG ENOSPC/; # stuff unless (defined(syswrite($socket,$buffer))) { # Oops, didn't write. How come? if ($! == EAGAIN) { # Nonblocking and socket not yet ready... } elsif ($! == EFBIG) { # Writing to a file that is too big for our filesystem. } elsif ($! == ENOSPC) { # Ooops, writing to a file and the disk is full. } else { # One of the other dozen or so reasons a write can fail. } }
    Now, in practice, you rarely need to worry about testing for errors like this. Blocking connections either work or fail permanently(Footnote 1). With non-blocking connections, if you make good use of the select(2) system call, your process will be told when sockets are ready to be read/written to. IO::Select is a wrapper to the select(2) system call which makes it a little more managable.

    An excellent example of the skeleton needed for a non-blocking, non-forking server can be found in The Perl Cookbook, Section 17.13.

    As to your original question of an example of using getpeername for detection, here's a short example:

    unless (defined(syswrite($socket,$buffer))) { # Oh dear, couldn't write. Could it be that I'm # no longer connected? if (defined(getpeername($socket))) { # Yup, they're still there. Must be a different error. } else { # Oops, the other side went away. } }
    I would strongly suggest using IO::Socket rather than using getpeername, simply because if($socket->connected) is much more understandable than the code above.

    Hope that all this helps. I haven't had my morning coffee yet, so some bits might be a little unclear. Feel free to quiz me more if you like.


    (Footnote 1) Not entirely true. Blocked reads and writes can be interrupted by signals, and I can't remember off the top of my head if perl automatically restarts the system call once you've dealt with the signal.

Log In?

What's my password?
Create A New User
and nobody stirs...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (12)
As of 2017-11-21 15:55 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (304 votes). Check out past polls.