#!/usr/local/bin/perl # $Id: echo.perl,v 1.6 2001/05/27 16:44:24 doug Exp $ # http://www.bagley.org/~doug/shootout/ use Socket; my $DATA = "Hello there sailor\n"; sub server_sock { local *SS; socket(SS, PF_INET, SOCK_STREAM, 0) or die "server/socket ($!)"; setsockopt(SS, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die "server/setsockopt ($!)"; bind(SS, sockaddr_in(0, INADDR_LOOPBACK)) or die "server/bind ($!)"; listen(SS, 2); return(*SS); } sub get_port { local *SK = shift; (sockaddr_in(getsockname(SK)))[0]; } sub client_sock { my $port = shift; local *CS; socket(CS, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "client/socket ($!)"; connect(CS, sockaddr_in($port, INADDR_LOOPBACK)) or die "client/connect ($!)"; return(*CS); } sub echo_client { my($N, $port) = @_; local *SOCK = client_sock($port); select(SOCK); $| = 1; for my $i (0..($N-1)) { print $DATA; my $ans = <SOCK>; ($ans eq $DATA) or die qq{client: "$DATA" ne "$ans"}; } close SOCK; } sub echo_server { my($N) = @_; local *SSOCK = server_sock(); my $port = get_port(*SSOCK); my $pid = fork; defined $pid or die "server/fork ($!)"; if ($pid) { # parent is server local *CSOCK; accept(CSOCK, SSOCK) or die "server/accept ($!)"; select(CSOCK); $| = 1; my $n = 0; while (<CSOCK>) { print $_; $n += length($_); } select(STDOUT); print "server processed $n bytes\n"; } else { # child is client echo_client($N, $port); } wait(); } sub main { my $N = $ARGV[0] || 1; echo_server($N); exit(0); } main();