Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

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

( #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) 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)
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.

    Cheers,
    Paul

    (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?
Username:
Password:

What's my password?
Create A New User
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (16)
As of 2015-07-06 17:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (78 votes), past polls