in reply to Re^2: chat between client and server
in thread chat between client and server

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.


___________
Eric Hodges

Replies are listed 'Best First'.
Re^4: chat between client and server
by eric256 (Parson) on Oct 11, 2007 at 21:25 UTC

    Here is a non-blocking client that sends and receives in separate threads

    #!/usr/bin/perl use strict; use warnings; use IO::Socket; use threads; my $server = new IO::Socket::INET( PeerAddr => '127.0.0.1', PeerPort => 1300, Proto => 'tcp', Reuse => 1); die "Client Couldn't connect to server: $!\n" unless $server; threads->create(sub { while (my $msg = <$server>) { print "Recieved: $msg"; } }); threads->create(sub { while (my $msg = <STDIN>) { print "Sending: $msg"; print $server $msg; } });

    And a server modified to echo its input. Can't use STDIN because all your clients would fight over it. Though you could create a single thread that listens and then broadcasts out to all clients.

    #!/usr/bin/perl use strict; use warnings; use threads; use IO::Socket; print "Starting server: $$\n"; my $server = IO::Socket::INET->new(LocalPort => 1300, Proto => 'tcp', Listen => 10, Reuse => 1); die "Failed to create socket: $!\n" unless $server; sub listen_to_client { my ($client) = @_; my $tid = threads->tid(); while (my $get = <$client>) { print "client ($tid) : $get"; print $client $get; }; print "Client closed\n"; close $client; } while (my $client = $server->accept()) { my $thr = threads->create("listen_to_client", $client); print "Client connected ", $thr->tid,"\n"; $thr->detach; }

    ___________
    Eric Hodges
      Good start, but your client needs a sleep() at the end, to keep it from connecting then exiting. Also the server dosn't have a thread to send original msgs to the client from STDIN. It's getting close though. The server memory usage stabilizes too, after repeated connects/disconnects from multiple clients.

      Update

      I did try this obvious code addition to add stdin capability, BUT server-stdin messages ONLY go to the first client. For instance, if I connect with 3 clients, server's stdin only gets sent to client 1. If I close client 1, server's stdin will go only to client 2, etc. Perplexing? Probably it needs an "array of connected clients" so it can print to all, or selected clients.

      #!/usr/bin/perl use strict; use warnings; use threads; use IO::Socket; print "Starting server: $$\n"; my $server = IO::Socket::INET->new(LocalPort => 1300, Proto => 'tcp', Listen => 10, Reuse => 1); die "Failed to create socket: $!\n" unless $server; sub listen_to_client { my ($client) = @_; my $tid = threads->tid(); while (my $get = <$client>) { print "client ($tid) : $get"; print $client $get; }; print "Client closed\n"; close $client; } sub stdin_to_client { my ($client) = @_; while (my $msg = <STDIN>) { print $client $msg; } print "stdin thread ended\n"; } while (my $client = $server->accept()) { my $thr = threads->create("listen_to_client", $client); my $thr1 = threads->create("stdin_to_client", $client); print "Client connected ", $thr->tid,"\n"; $thr->detach; $thr1->detach; }

      I'm not really a human, but I play one on earth. Cogito ergo sum a bum