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

function to count pending packets in TCP socket

by Anonymous Monk
on Jan 30, 2018 at 20:57 UTC ( #1208151=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks

I want to monitor an open TCP connection on my client, as the server may have silently died or network connection is broken so I would continue to write data on my TCP socket until the send window will be 0 and eventually I may lose the data. Unfortunately the server speaks a very simple protocol without any application layer acks. It entirely relies on TCP doing the job. This I cannot change

In Linux there is a command 'ss' which gives some status information regarding socket connections. In particular it provides 'send-q' which is the count of sent TCP packets not yet acknowledged by the peer. Is there any way to get this information by a Perl function?

I would like to use it in the following way (just pseudo code)

my $conn = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, +Proto => 'tcp'); die unless ($conn); syswrite($conn, "message content"); doSomeOtherStuff(); #by now, under normal conditions, message should have reached the peer + and be acknowledged my $pendingMessages = send_q($conn); #this is the function I am lookin +g for but have not found yet if ($pendingMessages) { #perform some recovery actions here. Stop sending messages, until al +l previous messages have been acknowledged }

It would be so great, if someone could give me a hint how to do it. Thank you! Andreas

Replies are listed 'Best First'.
Re: function to count pending packets in TCP socket
by salva (Abbot) on Jan 31, 2018 at 10:38 UTC
    I would continue to write data on my TCP socket until the send window will be 0 and eventually I may lose the data.

    That is not how TCP works: once the TCP sending buffer becomes full, the kernel would block any write operation until data is transmitted to the other side leaving some buffer space free again. No data is lost.

    If you don't want to block, you would have to use select or some of the modules wrapping it (or similar syscalls). For complex cases, using an event-driven programing framework such as AnyEvent, POE, Mojo::IOLoop, IO::Async, etc. may help too.

    Update: I forget to say that no data is lost in TCP operations, but you have to check the result of syswrite which is the number of bytes written. It is not guaranteed that syswrite would write all the data passed, so you will have to call it repeatly, adjusting the offset until all the data is sent (well, actually, buffered by the kernel!).

      Agree with salva, it sounds like Anonymous Andreas is describing UDP - where data can be lost due to packet loss since there is no acknowledgement unless you build something into the application layer. And if you're going to do that, you might as well use TCP, which handles acknowledgements for you. Take Telnet for example, once connected, a pretty simple protocol that just passes characters back and forth between client and server; yet riding on TCP, transmission is reliable. Unless I'm missing something from the OP?

Re: function to count pending packets in TCP socket
by thanos1983 (Vicar) on Jan 31, 2018 at 10:28 UTC

    Hello Anonymous Monk,

    I found this thread How can I test TCP socket status in Perl?. The accepted answer is:

    $socket = IO::Socket::INET(localhost, 1000); die "no connection" unless $socket -> connected(); $socket -> send("your face here for $20"); die "socket is dead" unless $socket -> connected(); $socket -> recv($data);

    Let us know if it works, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: function to count pending packets in TCP socket
by Anonymous Monk on Jan 31, 2018 at 18:08 UTC

    A side note - Send-Q refers to amount of data queued (bytes), not number of packets.

    Regarding your problem. Perhaps you could enable SO_KEEPALIVE on the socket, possibly with tweaked TCP_KEEP* values, so that recovery can happen in a timely manner? See Socket, socket(7), and tcp(7).

Re: function to count pending packets in TCP socket
by Anonymous Monk on Feb 01, 2018 at 22:04 UTC

    Dear Monks,

    Thank you for your replies and trying to help me. Please also forgive that my language is not always clear. I try to improve.

    I am speaking about TCP and not about UDP. Many think that data cannot be lost on TPC, unfortunately this is not always true. As long as both peers keep their sockets open and only the network is down for some time, the connection will recover, data transmission is repeated and nothing is lost. If, however, one side dies, the socket on the other side may still be open, so the application may continue writing data into this socket until it will block or eventually returns an error code. And obviously all this data will never arrive at the other side which is already dead.

    Testing $conn->connected() exactly fails in this sitation of a "half-open" TCP connection, since the local socket believes the connection is established. That is exactly the issue I want to detect

    It has been suggested to use SO_KEEPALIVE. Thank you for this idea. This indeed would resolve the issue, however it is not a viable solution. The problem here is, that the keepalive timeout typically is 2 hours. As far as I know, it can only be configured globally on a machine, so I don't want to play with this parameter, as it may cause side effects. I want to detect the half-open connection after a few seconds, ont only after hours. Some comments on the web suggest that the application should use its own heartbeat messages. However this will not work in my case. Unfortunately the application protocol is fixed, I cannot change it, and it does not provide a heartbeat message

    Pinging the peer hoat may be another way to check, if it is available. However, I would prefer send_q as it would use status data of the actual socket rather than introducing another channel.

    Thank you also for pointing out that send_q does not count the pending messages but the pending octets. Good to know, even though in my case this detail does not really matter. I would only be interested to test if send_q is 0 or not.

    Now I come back to my original question: Is there a function in Perl which returns the current value of send_q for an open TCP connection? Would be great, if someone knows the answer. Thanks again for your support. Best regards, Andreas

    I should add that in my case it would be fully sufficient if the application layer detects that something is "wrong" with that TCP connection. There are recovery mechanisms available in the code which only need to be triggered.

Re: function to count pending packets in TCP socket
by Anonymous Monk on Feb 09, 2018 at 06:56 UTC

    Dear Perl Monks,

    More than a week has passed since my last post in this thread without any reply. Hence I am assuming that nobody knows a Perl function which returns the send_q value of a socket connection. Meanwhile I helped myself by calling the Linux ss command from Perl and parsing its output. However I see this rather a work around than a clean solution. It imposes OS dependency and it creates a risk my program may fail in future, should any Linux update change the output format of the ss command.

    Therefore I am still interested, if a clean solution exists in Perl.

    Best regards

    Andreas

      The ss utility comes from iproute2 package. Sources are freely available for you to read and inspect. The utility is specific to Linux networking.

      Send-Q is obtained either via netlink(7), or parsing /proc/net/tcp (hexadecimal field named tx_queue). You could do the same in perl program: use getpeername and match the right line. Inefficient and cumbersome, but it might suit your purposes.

      Lastly, I would reconsider the approach of building HA/failover capabilities directly into application. Perhaps your questions are better answered on a networking related forum. HAProxy dot org for instance has a mailing list and archive. HtH.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1208151]
Approved by hippo
Front-paged by haukex
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2018-02-24 12:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When it is dark outside I am happiest to see ...














    Results (310 votes). Check out past polls.

    Notices?