perlnwb has asked for the wisdom of the Perl Monks concerning the following question:

I am learning the Socket API in Perl now. I am new to this, so I'm sorry if the question is stupid, but I have already searched the net with no results. I need to create one server and several clients. I have already created a client and a server and they are successfully communicating with each other, but now I need to have one server and many clients. The clients are sending some information to the server, which should handle it. Let me explain using simple example. The server is the handler for client requests, and it can display on a terminal screen the statistics of network usage or other information coming from the clients. I need to display all clients' information at once, so the server should have the ability to switch between them. Let's assume that there are four clients connecting to the server. At present the server displays only the second client's information. If I click some button it will switch to another available client in queue or just randomly, and now the information from the third client is displayed, and so on. I need to work with only one client at a time. Also I don't need to store information from clients if it isn't in focus right now. I have tried to create something like that, but I feel that I have a lack of knowledge now and need some more practice. Please provide any relevant examples which can help to implement this task. Or just some good direction to follow (books perhaps, or tutorials.)
  • Comment on How to serve multiple socket clients Perl

Replies are listed 'Best First'.
Re: How to serve multiple socket clients Perl
by choroba (Cardinal) on Mar 22, 2015 at 21:50 UTC
    Crossposted at StackOverflow. It's considered polite to inform about crossposting, so people not attending both sites don't waste their time hacking a problem already solved at the other end of the internet.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How to serve multiple socket clients Perl
by Anonymous Monk on Mar 23, 2015 at 03:49 UTC

    See the example at the end of perldoc IO::Select . Adding *STDIN to the select object will allow you to also process inputs from the terminal.

    This is the kind of problem that fits right into the wheelhouse of the various async modules - they do all the dirty work for you. Here's a list of some of them (from the Freenode IRC #perl channel):

    "Asynchronous event-driven IO is awesome in Perl with POE, Future/IO::Async, IO::Lambda, Mojo::IOLoop, Reflex, Promises, AnyEvent and Coro, among others. Maybe not AnyEvent. Or Coro."

Re: How to serve multiple socket clients Perl
by Laurent_R (Canon) on Mar 22, 2015 at 22:58 UTC
    I think that the best would be to show us some of your code. It is quite difficult to provide any guidance with such a general description of what you are doing.

    Je suis Charlie.
Re: How to serve multiple socket clients Perl
by SimonPratt (Friar) on Mar 23, 2015 at 11:03 UTC

    Some code would be good to see.

    Based on your description though, it sounds a lot like you have your "server" and "client" roles reversed, where the clients are listening for the server to connect to them.

    A more typical solution would be to have a server that is listening for inbound connections. Clients then make the connection to the server, pass their update to it and disconnect. The server can then decide what to do with the information it is given (whether it keeps it, uses it, caches it, discards it, whatever). Clients are then responsible for determining what to do when they cannot connect.

Re: How to serve multiple socket clients Perl
by locked_user sundialsvc4 (Abbot) on Mar 23, 2015 at 14:33 UTC

    You really can’t have “searched the net with no results.”   :-)   There are literally thousands of servers out there which are all implemented in mostly the exact same way:   with a select() loop.   (Many of them are built using existing server-building toolkits, such as the great-many ... say, POE ... that are available for Perl.   (Or, say, Twisted ... every language has several to choose from.)   “Actum Ne Agas:   Do not do a thing already done.™”)

    Conceptually speaking, the server sits there listening for incoming packets from any one of many simultaneously-open sockets.   (A single thread is doing this!)   When a packet arrives from any one of the sockets, the message is read, processed, and a reply is sent back on that socket.   Meanwhile, the server is also listening for new connection-requests.   If the replies can be made within a few milliseconds, nothing more than a single thread is needed.

    If the tasks that can be requested are such that it takes more than a trivial amount of time to do them, the server’s architecture becomes a little more complicated, because it is now managing a pool of worker-threads.   Apache Server (or any web-server, for that matter) is a quintessential example of this.

    The key point is to realize that whatever-it-is that you’re doing is not a new use-case, therefore you really don’t have to “invent” anything.   There is nothing to “build” here, and, since the available software is all free, nothing to “buy.”   Extremely sophisticated and battle-tested servers, and clients, can simply be lifted off the shelf.   To begin (in the case of Perl), surf to http://search.cpan.org and type the word server ...

      I cannot figure out how to switch between clients. I mean that I need to accept all possible connections, but I need to communicate only with one client at once, so other can send information, or if it possible to notificate them that now server is not instresting in your information, so you have to wait until it call you. I have only one , but stupid idea, so I am asking here for some better approach. As for my idea, clients are sending data to server for instance each second, server accpets this data and place it in array and when server switches to another client data it will read info from array assigned to this client. But here memory synchronization comes into play, so it is bad idea. It would be great to make it possible for server to switch beetween clients , other should sleep at this time, or something other not interrupting server , or to do this in way that doesn't affect on connection betw een server and focused client. I have no building block to do this taks, so I asked this question to get some advices or directions.

        Some examples of async servers in:

        https://blog.afoolishmanifesto.com/posts/concurrency-and-async-in-perl +/

        Here's some building blocks for you. It's just an extension of the example at the end of the IO::Select perldoc page with some features from your stated problem added.

        #!/usr/bin/perl # http://perlmonks.org/?node_id=1120916 use IO::Socket; use IO::Select; use strict; my ($port, $current, $cycle) = (shift // 6667); my $listen = IO::Socket::INET->new(LocalPort => $port, Listen => 9, Re +use => 1) or die "$@ opening socket on port $port"; my $sel = IO::Select->new($listen, 0); while(1) { for my $h ($sel->can_read) { if($h == $listen) { $sel->add(my $new = $h->accept); $current //= $new; print "accepted from: ", $new->peerhost, ":", $new->peerport, "\ +n"; } elsif($h == 0) { sysread STDIN, my $in, 1024; # ignore $current = (grep $_ > 0 && $_ != $listen, $sel->handles) [++$cycle % ($sel->count - 2 || 1)]; print $current ? "switch to " . $current->peerhost . ':' . $current->peerpor +t . "\n" : "no clients\n"; } elsif(sysread $h, my $in, 1024) { $h == $current and print $in; } else { $sel->remove($h); $h == $current and undef $current, print "client exited\n"; } } }

        As others (including me) have said, this kind of problem should be done in one of the async frameworks, but sometimes a plain example can make for a decent tutorial.

        Or not.

        You don't "switch between clients". Your callback gets data from all clients, and you simply ignore data from any client except the "current client" (keep a $currentclient :).

        Have a callback from STDIN to switch which client is the "current client".

        I hope this helps.