Since the OP didn't describe the error behaviour properly, here is my attempt:
The server starts OK, and as soon as I start a client the server exists silently.
The client accepts input from STDIN and terminates silently after the second line of input.
Update: I found one error: the server write to $so once instead of writing to $client twice. Fixing that fixes the program.
Second update: please note that this won't work with multiple clients because in the server multiple threads try to read from STDIN at the same time.
| [reply] [d/l] [select] |
nicely debugging ill try to make something up
thx
maybe someone will solve it quicker so i am still here
| [reply] |
| [reply] |
i've already read these topics and still hasnt find the answer
| [reply] |
Its a complex interaction to have multi-threaded client talking in a bidirectional manner to a mutithreaded server. To be honest, I've only seen 1 example of a multi-threaded server that worked, and that was with a forking client. You are jumping into very deep water, and you expect some simple looking scripts to have working complex functionality. I would suggest you study how the forking chat server-clients work first, before complicating it with threads. My first guess is that you need some IO::Select stuff in the threads. My second guess is that you create your threads after you create your IO::Socket object, so both threads get their own copy of the object. That probably raises havoc. I would try to create the threads before you make the IO::Socket, then share the socket filehandle with the threads thru a shared variable. Then you can have some IO::Select loop in the threads to detect when they are in a recv or send mode. You can't read when the socket is in send mode, and vice-versa.....thats called blocking. I don't want to discourage you from trying to figure this all out, but no one has done it before, and its for a reason. That reason is it involves alot of complex juggling of the socket filehandle, which you just sort of ignore with your simple code.
| [reply] |
wavenator:
If you're running the client and server on different machines, I'd expect that it wouldn't work. If they're on the same machine, seeing the error messages would be helpful.
Using strict & warnings might also shed some light on the subject.
...roboticus | [reply] |
no error code and when i put the warnning and strict still no wanrnnings
the problem is in the code somewhere
just dunno where
| [reply] |
wavenator:
I've loaded up the code, and added a couple of traces and fixed a minor bug. You're having some interaction problems with your console I/O. It works ... sort of. I've run out of time, so I'll give you back the code that I've tried, and show you the symptoms.
First, I added some traces, so I could see what was happening--Rather than wait for successful console input, I sent a message on both the client and server side so I could see that they both sent the expected messages. Then I discovered the minor bug: you were using $so instead of $client in the server.
Once I did that, the code started almost working. Basically, I could type some text on the server side, and it would appear on the client side. Similarly, I could type text on the client side and it would appear on the server side. But you have to alternate client & server, as successive messages aren't sent until it receives one from the other side.
Here's the slightly modified server:
#!/usr/bin/perl -w
use warnings;
use strict;
use threads;
use IO::Socket;
my $so = new IO::Socket::INET(LocalPort => '1300',
Proto => 'tcp',
Listen => 10,
Reuse => 1,);
my $client;
die "Socket Error: $!\n" unless $so;
sub start_thread1 {
print "thread1 started\n";
while(my $get=<$client>) {
print "client : $get";
}
print "thread1 ended\n";
}
sub start_thread {
print "thread started\n";
print $client "OK ... whaddaya want?\n";
while (my $msg = <STDIN>) {
print $client $msg;
}
print "thread ended\n";
}
while ($client = $so->accept()) {
my $thread = threads->create("start_thread");
my $thread1 = threads->create("start_thread1");
# This message appears to go nowhere ... we should use $client
+!
print $so "connected ... whatcha want?\n";
print "connected\n";
$thread->join();
}
And here's the client:
#!/usr/bin/perl -w
use warnings;
use strict;
use threads;
use IO::Socket;
my $so = new IO::Socket::INET( PeerAddr => '127.0.0.1',
PeerPort => 1300,
Proto => 'tcp',
Reuse => 1,);
die "Socket Error: $!\n" unless $so;
my $thread = threads->create(\&start_thread);
my $thread1 = threads->create(\&start_thread1);
sub start_thread {
print "thread\n";
while (my $txt=<$so>) {
print "server : $txt";
}
print "endthread\n";
}
sub start_thread1 {
print "thread1\n";
print $so "Client connected!\n";
while (my $msg = <STDIN>) {
print $so "$msg";
}
print $so "Client disconnected!\n";
print "thread1end\n";
}
$thread->join();
$thread1->join();
Unfortunately, I don't know why they're blocking. I don't use threads, so there are several possibilities: Blocking in the IO::Socket::INET module, blocking on your console I/O, console I/O interaction with threads, and others that I can't think of.
You might want to dig through perlipc and read perlfunc for more clues. I was expecting to see read and write calls in your code, so when I initially saw it, I was wondering how on earth it was supposed to work. I also didn't see any accept() calls, but apparently the IO::Socket::INET module takes care of that since I clearly see a connection and traffic taking place.
If I get an opportunity, I'll check into it some more after work. (Unless, of course, you've already got it solved by then....)
...roboticus | [reply] [d/l] [select] |
| [reply] |
Start it off simple. I like to build the server and telnet into it to start with. Gives you full control of the client while getting the server figured out. The following works, though i think there are probably some major issues with it memory wise. It is a nice simple start though.
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use IO::Socket;
my $server = IO::Socket::INET->new(LocalPort => 1300,
Proto => 'tcp',
Listen => 10,
Reuse => 1);
die "Failed to create socket: $!\n" unless $server;
my $client;
sub listen_to_client {
while (my $get = <$client>) {
print "client: $get";
};
print "Client closed\n";
}
while ($client = $server->accept()) {
print "Client connected\n";
threads->create("listen_to_client");
}
I ran it in one terminal, then telnet-ed in from two separate windows. Works like a charm.
| [reply] [d/l] |
didnt get my point
i didnt try to make s server program the controls more then 1 client
i've tried to make server+client that chats each other without IO Blocking
| [reply] |
Yes, and that is what this does. The server has multiple clients connecting to it that do not block each other while waiting. After this you use the same setup to build a client. The point was to start small and add features. Single client, multiple client, non-blocking multiple client connections, etc. This already does non-blocking reads from multiple clients. Doing the same thing in a client shouldn't be much harder. For non-blocking IO i don't think you want to use threads though, I think IO::Select is a better path to take.
Either way my point was that if you have complex client/server interactions like this, start as simple as possible adding features and testing constantly. You should then be able to pinpoint exactly where the code is broken and ask specific questions.
| [reply] |