I have this simply tcp proxy that I've written that is experiencing a bit of an issue.
Normally I would accept() a connection, fork() a child, and then select() between the client's socket and the remote system I am trying to proxy. This works well.
I thought that this time I would do this in one thread under one select(). This works well... When all of my clients are on fast connections.
This week I started up a perl script on some remote devices to pull a software update. These devices connect home via PPP over modem using a demand setup. Instead of spending 4 hours to download software they spread that over days grabbing 1M chunks. Assemble and then flash. This keeps the modem pool free.
The problem is that the lines are poor at some sites and the connection could be 19.2 or 9600. Most are at 38.4.
The write() from the server down (over modem) to the client
can block. This obviously slows down the whole process and can slow down the download for other devices. I switched back to a fork() method and of course no more problem, but I would like to make an attempt to fix this anyway.
My question here is more of "The Right Way(tm)" then strictly Perl.
while(1) {
for my $socket ($ioset->can_read) {
if ($socket == $server) {
new_connection($server, $remote_host, $remote_port);
}else {
next unless exists $socket_map{$socket};
my $remote = $socket_map{$socket};
my $buffer;
my $read = $socket->sysread($buffer, 512);
if ($read) {
$remote->syswrite($buffer);
} else {
close_connection($socket);
}
}
}
}
This script is just a stand-in script because these devices can't contact the remote directly. The server
side is running a XML-RPC interface, written in Perl, running under lighttpd.
For the fetch of pieces those are access via the same
web server as real files. Once
the slowness hits the XML-RPC calls can timeout because
they are so slow. A config save via XML-RPC can take over
5 minutes when this hits and using the child method it is
under a minute.
I could drop the buffer size of the read. Another option would be to convert to a non-blocking write and keep
track of what was written. Then try again. Of course I'll need to change the select logic to go back to waiting after
all those buffers have emptied. This would present a problem with devices connecting, but not in the available pool. They would have to wait for the other buffers to be clear before they would be acknowledged.
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.