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).
In reply to Re^3: Client/Server Question
by almut
in thread Client/Server Question
by commodorejim
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |