Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

select() on a client and server socket

by amir (Sexton)
on Jul 11, 2001 at 15:53 UTC ( #95643=perlquestion: print w/replies, xml ) Need Help??
amir has asked for the wisdom of the Perl Monks concerning the following question:

I have the following piece of code doing select().
my $extsock = socket connected to some server... my @ready; while(@ready = $select->can_read) { my $socket; for $socket (@ready) { if($socket == $listen) { my $new_socket = $listen->accept; Server->new($new_socket, $select, \@clients); } else { my $client = $clients[$socket->fileno]; if(defined $client) { &{$client->nextsub}(); } else { # unknown data??? } } } }
I am writing a server that listens on a socket and also connects to another server and sends/receives data on that socket. I want to be able to do this select() loop and have it handle both sockets, the server and the client. I connect $extsock to a client during a server request, so after I create a new Server object, that is when I connect to another server, and add that socket to select by doing:
$main::extsock = new IO::Handle; $main::extsock = IO::Socket::INET->new(.......); $self->select->add($main::extsock);
How do I figure out if the "unknown data" is coming from $extsock? Since right now, when data comes in on the client socket, $client is not defined!?

Thanks a lot,

Replies are listed 'Best First'.
Re: select() on a client and server socket
by bschmer (Friar) on Jul 11, 2001 at 16:18 UTC
    I'm a little fuzzy on exactly what you're trying to accomplish, so let me ramble a little...perhaps some of it may be relevant.

    Is the goal to have a single connection to the other server and multiple connections to clients, i.e. a multiplexer? If so, I would think that you wouldn't want to create a new Server object when you get a new connection from a client. Instead, you should add the new client connection into the select object. You seem to be set up this way since you have for $socket (@ready){, but from your description, my guess is that you added $extsock to the select object elsewhere.

    If you want multiple Server objects, you will need to give them control so that they can run their loop, most likely by calling fork or by calling the method that contains the code you listed. In that case, you would likely want to change the while to an if so that you don't block.

    All that aside, assuming that you insert all clients into the @clients array, your "unknown data" should be from $extsock. This is easy enough to check:

    if ($socket == $extsock){ print "Got data from extsock\n"; } else { print "Got data from an unknown handle ($socket)\n"; }
    I've been doing a *lot* of this kind of stuff lately, so if you can describe your goals in a little more detail, I can probably give you some code to help you out.
      I am writing a chat/instant messaging server.

      Normal chat clients connect to the server to chat, so for them I need to create an object to sustain their state, info, etc. The problem is when I try to connect two servers together, so that one server connects to the other and they can pass chat messages across.

      Scenario: server1, server2

      The admins of server1 and server2 want to join their chat servers, and make it a chat network. Both servers are listening for connections from chat clients. server1 makes a socket connection to server2. This socket will be used to pass chat messages from one server to the other. In this case server1 has to listen on its server socket and the other socket it has created, whereas server2 is only listening on its server socket.

      In server1's scenario, I add the connection to the other server to select from inside a Server object.

      OK, I know now how to figure out where the data is coming from (server1's server socket or server1's connection socket to server2).

      I have this code:

      my $select = IO::Select->new($listen); while(1) { my($r,$w) = IO::Select->select($select, $select, undef, 0); my $socket; for $socket (@$r) { ... } for $socket (@$w) { ... }
      AFAIK, the above code should block until it comes across a socket that is either readable or writeable.
Re: select() on a client and server socket
by bikeNomad (Priest) on Jul 11, 2001 at 17:42 UTC
    Assuming that you have a select() in your main loop instead of a can_read() (you should if you have more than one socket), you do this ($select is an IO::Select with both your sockets):

    my ($r, $w, $e) = IO::Select->select($select, $select, $select); foreach my $readable (@$r) { if ($readable == $serverSocket) { ... } elsif ($readable == $clientSocket) { ... } } # etc for $w (writable) and $e (exceptional)
    If you don't care about readability/writability/exceptions on a particular socket, build separate IO::Select objects with only those sockets of interest to pass to select().

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://95643]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2017-01-20 00:23 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (173 votes). Check out past polls.