Multithreading and sockets blocking I/O on Win32

D

Dragos D

Hello!

I'm posting here as a last, desperate attempt to solve a problems that made
me pull my hair off: I want to create (as a cradle for further development)
a simple, basic, transparent proxy server for any protocol, using threads
(the new model, "use threads" instead of "use Thread"). That is, only one
client will connect to the server, the server will connect in turn to a
remote server, then it will relay data from the remote server to the client,
and from the client to the remote server.

This has to run on Windows, so I'm using ActiveState Perl 5.0.8 build 805
running under Windows 98 SE.

After accepting a connection, the program launches one thread to read data
from the client and send it to the server, and another thread to read data
from the remote server and send it to the client. The idea is NOT to
interpret data in any way, just relay it until the client and the server
close the connection.

I chose as an example connecting to a POP3 server, pop.lycos.co.uk. OK, so I
run it, then fire up a telnet client and connect to localhost:8080. The
telnet client correctly sees the POP3 server's greeting message (+OK...),
then I type "hi" (an invalid command, which should produce a "-ERR" response)
but... the "hi" is NOT sent (packet sniffer reveals no traffic after the
+OK response). Accordingly, the last line I see on STDERR is:

TO remote: [hi] at ...

Suggesting that the "print {$remoteServer} $lineout, $EOL;" hangs the script.

Can someone please confirm this behaviour on Windows or infirm it on *nix?

And, if someone could point out what I'm doing wrong, I'd be the most
grateful.


Thanks for your time,
Dragos



#! perl -w

use IO::Socket;
use threads;
use strict;

my $EOL = "\015\012"; # the standard Internet line terminator
my $port = 8080;

my $listener = IO::Socket::INET->new(LocalPort=>$port, Listen=>5, Reuse=>1);
my $client=$listener->accept or die "Can't accept, $!";

my $remoteServer = IO::Socket::INET->new('pop.lycos.co.uk:110')
or die "Can't connect to remote server, $!";

my $threadTO = threads->create("ThreadTOremote");
my $threadFROM = threads->create("ThreadFROMremote");

$threadTO->join;
$threadFROM->join;

sub ThreadTOremote
{ my $lineout;
while (defined($lineout=<$client>))
{ $lineout=~s/(\x0D\x0A|\x0A\x0D|\x0D|\x0A|)$//; # strip any line ending
warn 'TO remote: [', $lineout, ']'; # <-- BLOCKS HERE !!!
print {$remoteServer} $lineout, $EOL;
warn 'After print TO remoteServer'; # this never gets displayed
}
}

sub ThreadFROMremote
{ my $linein;
while (defined($linein=<$remoteServer>))
{ $linein=~s/(\x0D\x0A|\x0A\x0D|\x0D|\x0A|)$//; # strip any line ending
warn 'FROM remote TO client: [', $linein, ']';
print {$client} $linein, $EOL;
warn 'After print to client';
}
}
 
N

Nicholas Dronen

DD> Hello!

DD> I'm posting here as a last, desperate attempt to solve a problems that made
DD> me pull my hair off: I want to create (as a cradle for further development)
DD> a simple, basic, transparent proxy server for any protocol, using threads
DD> (the new model, "use threads" instead of "use Thread"). That is, only one
DD> client will connect to the server, the server will connect in turn to a
DD> remote server, then it will relay data from the remote server to the client,
DD> and from the client to the remote server.

DD> This has to run on Windows, so I'm using ActiveState Perl 5.0.8 build 805
DD> running under Windows 98 SE.

DD> After accepting a connection, the program launches one thread to read data
DD> from the client and send it to the server, and another thread to read data
DD> from the remote server and send it to the client. The idea is NOT to
DD> interpret data in any way, just relay it until the client and the server
DD> close the connection.

DD> I chose as an example connecting to a POP3 server, pop.lycos.co.uk. OK, so I
DD> run it, then fire up a telnet client and connect to localhost:8080. The
DD> telnet client correctly sees the POP3 server's greeting message (+OK...),
DD> then I type "hi" (an invalid command, which should produce a "-ERR" response)
DD> but... the "hi" is NOT sent (packet sniffer reveals no traffic after the
DD> +OK response). Accordingly, the last line I see on STDERR is:

DD> TO remote: [hi] at ...

DD> Suggesting that the "print {$remoteServer} $lineout, $EOL;" hangs the script.

DD> Can someone please confirm this behaviour on Windows or infirm it on *nix?

It works on Linux.

$ ./foo
FROM remote TO client: [+OK POP3 server ready <[email protected]>] at ./foo line 39, <GEN2> line 1.
After print to client at ./foo line 41, <GEN2> line 1.
TO remote: [hi] at ./foo line 27, <GEN1> line 1.
After print TO remoteServer at ./foo line 30, <GEN1> line 1.
FROM remote TO client: [-ERR Unknown command.] at ./foo line 39, <GEN2> line 2.
After print to client at ./foo line 41, <GEN2> line 2.

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK POP3 server ready <[email protected]>
hi
-ERR Unknown command.
Connection closed by foreign host.

Regards,

Nicholas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,823
Latest member
Nadia88

Latest Threads

Top