in reply to Client/Server Question

The problem I'm having is how do I send the values I read in in the client program to the server program?

Like any other data you're already sending, e.g.

... my $name =<STDIN>; print $sock $name; # $name still holds the newline you got from STDI +N

Or maybe simply append it to the next message you're sending (i.e. "NAME"):

print $sock "NAME: $name";

That way, you could stick to your processing scheme server side, and just extract the sent part in question via regex capture:

/^NAME: (\w*)/ and ... # do something with $1

(Or have I misunderstood something?)

Replies are listed 'Best First'.
Re^2: Client/Server Question
by commodorejim (Novice) on Mar 06, 2010 at 22:37 UTC
    Thanks for your reply almut. I think I'm the one that's missed something as I'm completely new to Perl and a bit lost! So I do all of the processing server-side? Can you give me a quick example of how I might, for example, read in a name that someone's entered on the clint side and then check that name against a default name on the server side? I find Perl's syntax very fiddly and all of my attempts to do it so far have resulted in errors and infinite loops galore. Thanks so much for your help.

      The general problem with these things is that server and client have to agree on some protocol, i.e. that each party knows how to react in response to what the other side has done.  Here's your example modified to handle name and password checking with dynamic branching on the client side, in case re-entry of name or password is required.

      Server:

      #!/usr/bin/perl -w use strict; use IO::Socket; my $sock = new IO::Socket::INET( LocalHost => 'localhost', LocalPort => 7890, Proto => 'tcp', Listen => SOMAXCONN, Reuse => 1); $sock or die "no socket :$!"; STDOUT->autoflush(1); my $req_name = "Enter Name: \n"; my $req_pass = "Enter Password: \n"; my $req_none = "Enter \n"; sub verify_passw { my ($name, $pass) = @_; # print STDERR "name=$name, pass=$pass\n"; # debug # ... return 1; } while (my $new_sock = $sock->accept()) { my $name = ""; # lifetime is connection my $auth = 0; # ditto (storing state of session) while (<$new_sock>) { /^HELLO$/ and print($new_sock $req_name), next; /^NAME: (\w*)/ and do { $name = $1; if ($name && length($name)<=8) { print $new_sock "Ok, name: $name\n"; print $new_sock $req_pass; } else { print $new_sock "Invalid name: '$name'\n"; print $new_sock $req_name; } next }; /^PASS: (\w*)/ and do { my $pass = $1; if ($auth = verify_passw($name, $pass)) { # =, not == print $new_sock "Login ok\n"; print $new_sock $req_none; } else { print $new_sock "Invalid password!\n"; print $new_sock $req_pass; } next }; /^DATE$/ and print($new_sock scalar(localtime), "\n"), next; print $new_sock "DEFAULT\n"; } close $new_sock; }

      Client:

      #!/usr/bin/perl -w use strict; use IO::Socket; my $host = shift || 'localhost'; my $port = shift || 7890; my $sock = new IO::Socket::INET( PeerAddr => $host, PeerPort => $port, Proto => 'tcp'); $sock or die "no socket :$!"; my %handler = ( Name => \&name, Password => \&pass, ); sub show_reply_and_next { do { $_=<$sock>; print unless /Enter $/; } until /^Enter (\w*)/; # $1 holds what to do next if ($handler{$1}) { $handler{$1}->(); } # else just return } sub hello { print $sock "HELLO\n"; show_reply_and_next(); } sub name { my $name = <STDIN>; print $sock "NAME: $name"; show_reply_and_next(); } sub pass { my $pass = <STDIN>; print $sock "PASS: $pass"; show_reply_and_next(); } ### hello(); # initiates login print $sock "DATE\n"; print scalar <$sock>; print $sock "NONE\n"; print scalar <$sock>; close $sock;

      Sample session:

      $ ./827156_client.pl Enter Name: toooooooo_long Invalid name: 'toooooooo_long' Enter Name: Invalid name: '' Enter Name: almut Ok, name: almut Enter Password: foobar Login ok Sun Mar 7 01:10:53 2010 DEFAULT

      It's maybe worth noting that in real life the server should not allow access to any "protected" resources unless the login has successfully been completed. The idea being that a client program with possibly manipulated logic of flow will have no chance to bypass security checks.  This is not implemented so far — the code just sets $auth (which should then be used for subsequent checks).

        Brilliant! Thanks so mch for you help almut. I'll pore over this code later to make sense of it. Thanks also to jethro for your input. You guys are lifesavers.

      If you didn't do the checking on the server side, you would have a big security hole. An attacker could just eliminate any checks in your client program or write his own client without any checking of a password.

      This would be similar to a security guard asking someone who wants to enter: "Do you know the password? Is it the correct one?" and when he gets the answer "Yes and yes" to let him in.