To be sure, similar questions have been asked before. I found tye's answer to be most helpful -- though it's from a totally different thread.
I have a socket that I wish to use from two threads. It's not a Listen socket. My &listener dies after a while though. This death is reliable, though you can't really say when before hand. If I do the same test without threads it works fine, so I figure I need to dup the IO::Socket. The problem with tye's "<&".fileno($sock) is that it returns an IO::Handle, and I wish to call the connected() from IO::Socket later.
Please help. Here is a small sample of what I'm trying to do:
my $sock = new IO::Socket::INET(
PeerAddr => "igs.joyjoy.net",
PeerPort => "6969", Proto => "tcp" );
my $sender = new threads( \&sender => $sock );
my $listener = new threads( \&listener => $sock );
$sender->join;
$listener->join;
exit;
sub sender {
my $sock = shift;
print $sock $_ while <>;
}
sub listener {
my $sock = shift;
while( $sock->connected ) {
my $msg = "";
my $sock_addr = recv( $sock, $msg, 1024, 0 );
unless( defined $sock_addr ) { die "socket error"; }
SHOW: {
local $| = 1;
print $msg;
}
}
}
I also realize there are modules like [mod://Net::Telnet] that do a lot of this stuff for you, but I wish to learn how to do this by hand.
UPDATE (several hours later): It doesn't die at all, the recv() quits stuffing data into $msg though. It doesn't return undef either, as it would if there were an error, and it stays connected() because it starts looping really fast through the while(). I guess I have no idea why the code above doesn't work.
UPDATE II (1/5/6): I changed the code above around a little. This code actually does work as an IGS client. However, very occasionally the recv() will begin to get 0 results back and the while() loop starts firing a billion times a second (never to recover). This happens more frequently with a version where I pass fileno() and $newiosocket->fdopen($fileno, "+>") in each thread instead.
Also, you can't my $sock : shared. I tried that. It generates a "stupid type to share" error or something like that.
Anyway ... Thanks for you input. I actually did try the things you suggested.
I have yet to try a $new_socket->fdopen( $id, "+>" ) though. It's worth a shot. But I think the actual problem relates to the wrong choice of recv(). I'm pretty sure I need to also try read() with atmark() instead.
Do you have to flush the socket (or something) somehow when you use recv()? Ultimately I need to do a lot more experiments. This project should not be difficult. *sigh*
If I do the same test without threads it works fine...
Really? Could you show me your non-threaded code that allows you to be both server and client talking through the same port and the same IO::Socket::INET handle at the same time?
Because that is what you are trying to do in the above code.
I'm experimenting with the $sock=new IO::Socket; $sock->fdopen() that someone linked to. Perhaps that'll fix me up.
C.
Well maybe, but it is very confusing code.
He makes a client style connect to a remote system and port. He then passes the socket, without having checked whether the connection succeeded to two threads.
One of those threads labelled 'sender', sits in a tight loop reading from <> (presumably intended to be STDIN) and sends whatever it reads to the remote system in a tight loop. It never checks whether the socket is connected, is is still connected.
The other thread, labelled 'listener' despite that it does use 'listen', sits and attempts to receive anything that arrives on the the port and echo it to standard out. This does check whether the port is connected, but just then just falls off the end of the thread. It also just dies if the recv fails. IN either case, there is no attempt to coordinate termination with the sender thread, which will just continue to attempt to read and send forever.
The OP claimed that "If I do the same test without threads it works fine", but with an absence of any calls to listen, connect or accept, and no coordination between reads and writes, it is very difficult to see how that could ever be.
Essentially, the OP appears to be leaping into threads without making any attempt to understand the basics of socket communications in a non-threaded environment. I had hoped to solicit a response that would allow me to work further in trying to assist him, but he does seem to want to start at the beginning :(
perlmonks.org content © perlmonks.org and Anonymous Monk, BrowserUk, castaway, jettero, zentara
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03