Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

connect() & close()

by monktim (Friar)
on Oct 12, 2004 at 21:16 UTC ( #398700=perlquestion: print w/replies, xml ) Need Help??

monktim has asked for the wisdom of the Perl Monks concerning the following question:

What are the ramifications of calling connect() for an INET Socket Stream repeated times without calling close()? I was sending messages over a socket and immediately called close() after each send session was done. I found my messages were getting lost. When I ran with a breakpoint on my send() the msgs were delivered!

Next I tried the code with a sleep before the close() and that worked too. Not calling close() at all also worked. I don't wait for an ACK msg from the server, it doesn't send one. The server isn't mine so I can't add the ACK response and close the socket after the ACK.

It looks like I can close the socket before the msg is delivered to the server. When this happens the msg gets lost. Is this in fact what is happening?

How should I handle this? I'm probably going to remove the close() call since the connect() and send() happen less than 100 times an hour. Does that sound reasonable?

Thanks in advance.

janitored by ybiC: Fix typo in nodetitle - s/cose/close/;

Update: I'm using Perl 5.6.1 build 631 on Win32. I'm using Socket with tcp and I have output autoflush on.

Replies are listed 'Best First'.
Re: connect() & close()
by pg (Canon) on Oct 12, 2004 at 21:52 UTC
    "It looks like I can close the socket before the msg is delivered to the server. When this happens the msg gets lost. Is this in fact what is happening?"

    I assume we are talking about TCP. Yes, you are right that you can close socket before the message is delivered. However the connection is not really closed until the message is delivered. The connection is said in a lingering state (this is the formal terminology, lingering). The connection is really gone, when all pending data are sent. So look for some other reason ;-)

    "I'm probably going to remove the close()"

    No, not a good idea. Again, inspect your code and look for some other reason for your failure. This is not it.

    "Not calling close() at all also worked."

    But you are risking to have all usable local port used up.

Re: connect() & close()
by tachyon (Chancellor) on Oct 12, 2004 at 22:21 UTC

    As pg points out once you have sent the data you should be able to close the socket. Closing a socket should not lead to the loss of lingering (aka buffered send) data. As he also points out if you don't close your sockets you may use up all the available file descriptors on your system. They will not time out for at least several hours. On Win32 you will only have ~512 by default. On *nix you should have ~1024 so it is quite easy to use them all if you don't close sockets in a process.

    Are you using Socket or IO::Socket::INET? Can you show a short test case? You may find benefit setting the TCP_NODELAY flag to bypass Nagle's algorithm. I found this reference to SO_LINGER on the Socket FAQ

    Closing a socket: if SO_LINGER has not been called on a socket, then close() is not supposed to discard data. This is true on SVR4.2 (and, apparently, on all non-SVR4 systems) but apparently not on SVR4; the use of either shutdown() or SO_LINGER seems to be required to guarantee delivery of all data.

    NB SVR4 systems include Solaris 2.x, SCO ODT 3.0, AIX, A/UX.

    Although I agree with pg that it should not happen why not try calling shutdown on the socket before you close it or specifically setting the TCP_NODELAY and SO_LINGER options. You might also try syswrite to send your data, instead of send. This bypasses both the send interface and stdio.

    cheers

    tachyon

      try what tachyon said. In case you need to know the syntax as how to set SO_LINGER, here is an example:

      setsockopt(BROWSER_LISTENER, SOL_SOCKET, SO_LINGER, pack("l", 1)) || d +ie "Failed to setsockopt: $!";
      Thanks for the reply tachyon (and pg). I'm using Perl v5.6.1 build 631 on Win32. I'm also using Socket for TCP. I do have output autoflush on. I have it set at the top of the script $|=1; and I have select((select($socket), $|=1)[0]);

      I tried all combinations of TCP_NODELAY and SO_LINGER but I still didn't get consistent results. Printing to the socket seems to work intermittently when I use those options or when I use no options at all.

      If I call shutdown with 0, 1 or 2 and follow it with a close the msg doesn't get delivered. If I get rid of the close and just call shutdown with a 1 or 2 the msg doesn't get delivered. If I call shutdown($socket, 0) without a following close then the msg does get delivered.

      I found the Socket FAQ to be an excellent resource. Thanks for the link. I found this part especially good. "Nagle's algorithm collects small packets together (no more than .2sec delay) and thereby reduces the amount of overhead bytes being transferred.". This is why the sleep 1; before the close worked. Even though I specified TCP_NODELAY, it appears that it is still buffering.

      I write to the socket like this print $socket (pack("N", length($msg)), $msg); What would a similar syswrite look like? I can't seem to get syswrite to work at all. Syswrite will be my last test before I try and post some code. The sever is written in C++ so I'll have to try and emulate it and I'm not sure I'll have the same results in Perl.

      Thanks again everyone.

Re: connect() & close()
by dave_the_m (Monsignor) on Oct 12, 2004 at 23:00 UTC
    What are the ramifications of calling connect() for an INET Socket Stream repeated times
    In that case, you should get the error EISCONN, "The socket is already connected."

    Dave.

Re: connect() & close()
by Scarborough (Hermit) on Oct 13, 2004 at 13:08 UTC
    This has caused me some concern I have a simple server fielding requests across a network and I have the following code.
    while ($conn = $sock->accecpt()){ $conn->recv($buff, 1000); #do something with the $buff }

    Should I be closeing $conn if so at which piont.

Re: connect() & close()
by quai (Novice) on Oct 13, 2004 at 17:18 UTC
    You have autoflush enabled right? Sounds like a buffer that needs to be sent before closing the socket. (Im no socket expert)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://398700]
Approved by pikus
Front-paged by pikus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2022-08-10 16:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?