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

For various reasons I have a requirement to have an app listening on localhost which is proxying output from another app that is not under my control. Currently the OS is buffering too much data (I think >XP the OS buffers >64KB ish?) and I need to try and find a way to crank down the OS buffers without making a system wide registry change

The solution appeared to be to use the TCP_MAXSEG option:
  setsockopt($server, &Socket::IPPROTO_TCP, &Socket::TCP_MAXSEG, 2048);

However, on activestate at least this is giving me:
  Your vendor has not defined Socket macro TCP_MAXSEG, used at xxx

Any ideas on how I can control OS buffering on Win32? (I need it portable eventually, but win32 is my problem right now)

I believe that the trick on windows is to set the advertised MSS window (as above) and this then changes the window size that the sender uses

Right now I can use SO_RCVBUF on the receiving side to turn down the receive buffer, but I am still having problems with the sending buffer (which is outside my control) being way too large for my requirements

Any help please?

Replies are listed 'Best First'.
Re: Control TCP_MAXSEG (OS buffering) on Win32
by BrowserUk (Patriarch) on Nov 08, 2007 at 13:42 UTC

    I think that you are out of luck.

    The Windows platform setsockopt docs don't explicitly mention this option in the table of "BSD options not supported for setsockopt are shown in the following table." about half way down the page.

    However, if you look at the equivalent table for getsockopt, it is explicitly listed as unsupported.

    That said, and without any knowledge of how this stuff works on *nix/BSD et al, I think that you are being naive to believe that setting the maximum segment size in the receiving application is going to have any affect at all on how much the sending application will choose to buffer.

    My (limited) understanding of how this stuff works is that the TCP_MAXSEG has little or nothing to do with Application Layer(1) or Session layer(3) of the OSI stack which is where buffering occurs, but is at the Transport Layer(4). Meaning that it's value affects all communications between this end point and the down stream node, and is therefore a TDI layer configuration option, not a dynamic runtime option. It should only be configured on the basis of the type of pipe between nodes:ie. Dial-Up Modem -v- Cable Modem -v- PPPoE -v- ADSL/HDSL/VDSL -v- ISDN -v- Kilostream -v- Megastream etc.

    If you could change it change it dynamically from an application, it would affect all communications from this end point and it's upstream partners--which seems like a bad idea to me.

    I think it could be a bit of TheWildgoose chase :)


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Control TCP_MAXSEG (OS buffering) on Win32
by weismat (Friar) on Nov 08, 2007 at 22:32 UTC
    I checked quickly on MSDN and I found this article. I guess you must change the registry to influence the OS buffering.

      OK, well to rephrase the requirement:

      I have a 20KB/min (!) connection and the OS is currently buffering 3-4 mins worth of data, so I need to find a way to crank down the amount of buffering between the two apps, ie all I can do is affect the advertised receive window of the server socket which the remove app connects to (over localhost)

      Given a set of machines running XP and Vista can anyone think of a way to control advertised receive window?

      Curiously under Vista it seems that setting SO_RCVBUF controls the advertised window nicely - however, it looks like something wierd like 40KB ish + SO+RCVBUF on XP... (Need to repeat that test to remind myself of the magic number, however, I think it *wasn't* 64KB which would have been the obvious answer...)

      I can post some test code if it's useful?

        20KB/min? hmmm... for very slow connections, sometimes UDP would be a better option.