Echo Client/Server Back to the Win32 Shootout
Back to dada's perl lab

[The Original Shootout]   [NEWS]   [FAQ]   [Methodology]   [Platform Details]   [Acknowledgements]   [Scorecard]  
All Source For Echo Client/Server
echo.cygperl
#!/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();
echo.erlang
%%% -*- mode: erlang -*-
%%% $Id: echo.erlang,v 1.6 2001/06/09 00:02:04 doug Exp $
%%% http://www.bagley.org/~doug/shootout/
%%% with help from Sebastian Strollo

%%% TBD - need to add check for valid response.

-module(echo).
-export([main/0, main/1, client/2, server/1]).

-define(DATA, <<"Hello there sailor\n">>).

main() -> main(['1']).
main([Arg]) ->
    N = list_to_integer(atom_to_list(Arg)),
    ServerSock = create_server_sock(),
    spawn(?MODULE, client, [N, socket_port(ServerSock)]),
    server(ServerSock),
    init:stop().

create_server_sock() ->
    {ok, LSock} = gen_tcp:listen(0, [binary]),
    LSock.

socket_port(Sock) ->
    {ok, Port} = inet:port(Sock),
    Port.

client(N, ServerPort) ->
    {ok, Sock} = gen_tcp:connect("localhost", ServerPort, [binary]),
    client_loop(N, Sock),
    gen_tcp:close(Sock).

client_loop(0, Sock) -> ok;
client_loop(N, Sock) ->
    ok = gen_tcp:send(Sock, ?DATA),
    receive
    {tcp, Sock, _} -> client_loop(N-1, Sock);
    {tcp_closed, Sock} -> ok
    end.

server(LSock) ->
    {ok, Sock} = gen_tcp:accept(LSock),
    server_loop(Sock, 0),
    gen_tcp:close(LSock).

server_loop(Sock, Bytes) ->
    receive
    {tcp, Sock, Packet} ->
        ok = gen_tcp:send(Sock, Packet),
        server_loop(Sock, Bytes + size(Packet));
    {tcp_closed, Sock} ->
        io:format("server processed ~w bytes~n", [Bytes]),
        gen_tcp:close(Sock)
    end.
echo.gcc
/* -*- mode: c -*-
 * $Id: echo.gcc,v 1.9 2001/06/28 03:04:47 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>


typedef int (*SOCKACTION_P)(int,struct sockaddr *,socklen_t);
#define DATA "Hello there sailor\n"

void myabort (char *m) { fprintf(stderr, "%s\n", m); exit(1); }
void sysabort (char *m) { perror(m); exit(1); }

int sigchld = 0;
void reaper (int sig) { sigchld = 1; }

int 
genericSock(int port,SOCKACTION_P action,char *actionExceptionText) {
    int ss, optval = 1;
    struct sockaddr_in sin;
    if ((ss = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    sysabort("socket");
    if (setsockopt(ss, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
    sysabort("setsockopt");
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sin.sin_port = port; 
    if (action(ss, (struct sockaddr *)&sin,(socklen_t)sizeof(sin)) == -1)
    sysabort(actionExceptionText);

    return(ss);
}

int
server_sock () {
    int ss = genericSock(0,(SOCKACTION_P)bind,"server/bind");
    return(listen(ss,2),ss);
}

int
client_sock (int port) {
    return(genericSock(port,(SOCKACTION_P)connect,"client/connect"));
}

int
get_port (int sock) {
    struct sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    if (getsockname(sock, (struct sockaddr *)&sin, &slen) == -1)
    sysabort("server/getsockname");
    return(sin.sin_port);
}    

void
echo_client (int n, int port) {
    int i, sock, olen, len, nwritten, nread;
    char *offset, obuf[64], ibuf[64];
    char *end = ibuf + sizeof(ibuf);

    sock = client_sock(port);
    strcpy(obuf, DATA);
    olen = strlen(obuf);
    for (i=0; i<n; i++) {
    len = olen;
    offset = obuf;
    while (len > 0) {
        if ((nwritten = write(sock, offset, len)) == -1)
        sysabort("client/write");
        offset += nwritten;
        len -= nwritten;
    }
    offset = ibuf;
    while ((nread = read(sock, offset, (end - offset))) > 0) {
        offset += nread;
        if (*(offset-1) == '\n') break;
    }
    if (nread == -1)
        sysabort("client/read");
    *offset = 0;
    if ((strcmp(obuf, ibuf)) != 0) {
        char mbuf[128];
        sprintf(mbuf, "client: \"%s\" ne \"%s\"", obuf, ibuf);
        myabort(mbuf);
    }
    }
    close(sock);
}

void
echo_server (int n) {
    int ssock, csock, len, nwritten, total_bytes;
    pid_t pid;
    char buf[64], *offset;
    struct sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    int status;

    ssock = server_sock();
    signal(SIGCHLD, reaper);
    if ((pid = fork()) == -1)
    sysabort("server/fork");
    if (pid) {
    
    if ((csock = accept(ssock, (struct sockaddr *)&sin, &slen)) == -1)
        sysabort("server/accept");
    total_bytes = 0;
    while ((len = read(csock, buf, sizeof(buf))) > 0) {
        if (sigchld) myabort("server/sigchld");
        offset = buf;
        total_bytes += len;
        while (len > 0) {
        if ((nwritten = write(csock, offset, len)) == -1)
            sysabort("server/write");
        offset += nwritten;
        len -= nwritten;
        }
    }
    if (len == -1)
        sysabort("server/read");
    close(csock);
    fprintf(stdout, "server processed %d bytes\n", total_bytes);
    } else {
    
    echo_client(n, get_port(ssock));
    }
    wait(&status);
}

int
main(int argc, char *argv[]) {
    echo_server((argc == 2) ? atoi(argv[1]) : 1);
    return(0);
}
echo.ghc
-- $Id: echo.ghc,v 1.2 2001/05/01 20:19:52 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- Haskell echo/client server
-- written by Brian Gregor
-- compile with:
--      ghc -O -o echo -package net -package concurrent -package lang echo.hs

module Main where

import SocketPrim
import Concurrent
import System (getArgs,exitFailure)
import Exception(finally)
import MVar

server_sock = do
    s <- socket AF_INET Stream 6
    setSocketOption s ReuseAddr 1
    bindSocket s (SockAddrInet (mkPortNumber portnum) iNADDR_ANY)
    listen s 2
    return s

echo_server s = do
    (s', clientAddr) <- accept s
    proc <- read_data s' 0
    putStrLn ("server processed "++(show proc)++" bytes")
    sClose s'
    where
       read_data sock totalbytes = do
             (str,i) <- readSocket sock 19
         if (i >= 19) 
            then (do
              writ <- writeSocket sock str
              read_data sock $! (totalbytes+(length $! str)))
            else (return totalbytes)

local        = "127.0.0.1"        
message        = "Hello there sailor\n"
portnum     = 7001

client_sock = do
    s <- socket AF_INET Stream 6
    ia <- inet_addr local
    connect s (SockAddrInet (mkPortNumber portnum) ia)
    return s

echo_client n = do
    s <- client_sock
    drop <- server_echo s n
    sClose s
    where
      server_echo sock n 
          | n > 0 =(do 
                       writeSocket sock message
                   (str,i) <- readSocket sock 19
                       if (str /= message) then (do exitFailure)
                       else server_echo sock (n-1))
          | otherwise = (return [])

main = do 
     ~[n] <- getArgs
     -- server & client semaphores
         --get the server socket
         ssock <- server_sock 
     -- fork off the server
     s <- myForkIO (echo_server ssock)
     -- fork off the client
     c <- myForkIO (echo_client (read n::Int))
     -- let 'em run until they've signaled they're done
         join s ; join c

-- these are used to make the main thread wait until
-- the child threads have exited
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
  mvar <- newEmptyMVar
  forkIO (io `finally` putMVar mvar ())
  return mvar

join :: MVar () -> IO ()
join mvar = readMVar mvar
echo.guile
#!/usr/local/bin/guile -s
!#

;;; $Id: echo.guile,v 1.3 2001/06/29 23:12:36 doug Exp $
;;; http://www.bagley.org/~doug/shootout/
;;; from Brad Knotwell

(use-modules (ice-9 format))
(define DATA "Hello there sailor\n")
(define bufferSize (string-length DATA))

(define (echo-client n port-number)
  (let ((new-sock (socket AF_INET SOCK_STREAM 0))
    (buf (make-string bufferSize)))
    (begin (connect new-sock 
            AF_INET 
            INADDR_LOOPBACK
            port-number)
       (do ((i 0 (1+ i)))
           ((= i n) (close new-sock))
         (begin 
                 (send new-sock DATA)
         (recv! new-sock buf)
                 (if (not (string=? buf DATA)) (throw 'badData)))))))

(define (echo-server n)
  (let ((sock (socket AF_INET SOCK_STREAM 0)))
    (begin (setsockopt sock SOL_SOCKET SO_REUSEADDR 1)
       (bind sock AF_INET INADDR_LOOPBACK 0)
       (listen sock 2)
       (let ((pid (primitive-fork)))
         (if (= pid 0)
         (echo-client n (array-ref (getsockname sock) 2)) 
         (let ((new-sock (car (accept sock)))
               (buf (make-string bufferSize))
               (num-read 0))
           (do ((i (recv! new-sock buf) (recv! new-sock buf)))
               ((= 0 i) (begin (waitpid pid WNOHANG)
                       (display (format "server processed ~D bytes\n" num-read))))
             (send new-sock buf) (set! num-read (+ num-read i)))))))))
  
(echo-server (or (and (= (length args) 2) (string->;number (cadr args))) 1))

echo.ici
// $Id: echo.ici,v 1.0 2003/01/03 11:26:00 dada Exp $
// http://dada.perl.it/shootout
//
// contributed by Tim Long

/*
 * This is a thread based version of the client-server echo test.
 * sys.fork() is available on UNIX-like systems, but is not core
 * language, and is not available on Windows.
 */
n = argv[1] ? int(argv[1]) : 1;
data = "Hello there sailor\n";

static
echo_client(n, port)
{
    sock := net.connect(net.socket("tcp/ip"), port);
    for (i := 0; i < n; ++i)
    {
        net.send(sock, data);
        if ((ans := net.recv(sock, nels(data))) != data)
            printf("received \"%s\", expected \"%s\"", ans, data);
    }
    net.close(sock);
    return 1;
}

ssock = net.listen(net.bind(net.socket("tcp/ip"), 0));
client = thread(echo_client, n, net.getportno(ssock));
csock = net.accept(ssock);
t = 0;
while (str = net.recv(csock, nels(data)))
{
    net.send(csock, str);
    t += nels(str);
}
waitfor(client.result; client)
    ;
printf("server processed %d bytes\n", t);
echo.java
// $Id: echo.java,v 1.4 2001/06/01 12:40:29 doug Exp $
// http://www.bagley.org/~doug/shootout/
// author: Dirus@programmer.net

import java.io.*;
import java.net.*;

public class echo {
    public static void main(String[] args) throws Exception {
    int iIterations = 1;
    try {
        iIterations = Integer.parseInt(args[0]);
    } catch(Exception e) { }

    EchoServer esServer = new EchoServer(0);
    new EchoClient(InetAddress.getLocalHost(), esServer.getPort(), iIterations);
    }
}

class EchoClient extends Thread {
    private static final String GREETING = "Hello there sailor\n";
    private final InetAddress inetaServer;
    private final int         iPort;
    private final int         iIterations;

    public EchoClient(InetAddress inetaServer, int iPort, int iIterations) {
    this.inetaServer = inetaServer;
    this.iPort = iPort;
    this.iIterations = iIterations;
    start();
    }

    public void run() {
    Socket socketFromServer = null;
    try {
        socketFromServer = new Socket(inetaServer, iPort);
        BufferedReader in = new BufferedReader(new InputStreamReader(socketFromServer.getInputStream()));
        OutputStream out = socketFromServer.getOutputStream();

        byte[] bytesOut = GREETING.getBytes();
        String strIn = GREETING.trim();
        for(int i = 0; i < iIterations; ++i) {
        out.write(bytesOut);
        out.flush();
        String strRead = in.readLine();
        if(!strRead.equals(strIn))
            throw new RuntimeException("client: \"" + strIn + "\" ne \"" + strRead + "\"");
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

    try {
        socketFromServer.close();
    } catch(Exception e) { }
    }
}

class EchoServer extends Thread {
    private static final int   BUFFER_SIZE = 1024;
    private final ServerSocket ssAccepting;
    private final int          iPort;

    public EchoServer(int iPort) throws IOException {
    ssAccepting = new ServerSocket(iPort);
    this.iPort = ssAccepting.getLocalPort();
    start();
    }

    public final int getPort() {
    return iPort;
    }

    public void run() {
    byte bytesIn[] = new byte[BUFFER_SIZE];
    try {
        Socket socketClient = ssAccepting.accept();
        InputStream in = socketClient.getInputStream();
        OutputStream out = socketClient.getOutputStream();
        int iLength, iCount = 0;
        while ((iLength = in.read(bytesIn)) != -1) {
        out.write(bytesIn, 0, iLength);
        out.flush();
        iCount += iLength;
        }
        System.out.println("server processed " + iCount + " bytes");
    } catch (Exception e) {
        e.printStackTrace();
    }
    }
}
echo.mingw32
/* -*- mode: c -*-
 * $Id: echo.gcc,v 1.9 2001/06/28 03:04:47 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>


typedef int (*SOCKACTION_P)(int,struct sockaddr *,socklen_t);
#define DATA "Hello there sailor\n"

void myabort (char *m) { fprintf(stderr, "%s\n", m); exit(1); }
void sysabort (char *m) { perror(m); exit(1); }

int sigchld = 0;
void reaper (int sig) { sigchld = 1; }

int 
genericSock(int port,SOCKACTION_P action,char *actionExceptionText) {
    int ss, optval = 1;
    struct sockaddr_in sin;
    if ((ss = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    sysabort("socket");
    if (setsockopt(ss, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
    sysabort("setsockopt");
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sin.sin_port = port; 
    if (action(ss, (struct sockaddr *)&sin,(socklen_t)sizeof(sin)) == -1)
    sysabort(actionExceptionText);

    return(ss);
}

int
server_sock () {
    int ss = genericSock(0,(SOCKACTION_P)bind,"server/bind");
    return(listen(ss,2),ss);
}

int
client_sock (int port) {
    return(genericSock(port,(SOCKACTION_P)connect,"client/connect"));
}

int
get_port (int sock) {
    struct sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    if (getsockname(sock, (struct sockaddr *)&sin, &slen) == -1)
    sysabort("server/getsockname");
    return(sin.sin_port);
}    

void
echo_client (int n, int port) {
    int i, sock, olen, len, nwritten, nread;
    char *offset, obuf[64], ibuf[64];
    char *end = ibuf + sizeof(ibuf);

    sock = client_sock(port);
    strcpy(obuf, DATA);
    olen = strlen(obuf);
    for (i=0; i<n; i++) {
    len = olen;
    offset = obuf;
    while (len > 0) {
        if ((nwritten = write(sock, offset, len)) == -1)
        sysabort("client/write");
        offset += nwritten;
        len -= nwritten;
    }
    offset = ibuf;
    while ((nread = read(sock, offset, (end - offset))) > 0) {
        offset += nread;
        if (*(offset-1) == '\n') break;
    }
    if (nread == -1)
        sysabort("client/read");
    *offset = 0;
    if ((strcmp(obuf, ibuf)) != 0) {
        char mbuf[128];
        sprintf(mbuf, "client: \"%s\" ne \"%s\"", obuf, ibuf);
        myabort(mbuf);
    }
    }
    close(sock);
}

void
echo_server (int n) {
    int ssock, csock, len, nwritten, total_bytes;
    pid_t pid;
    char buf[64], *offset;
    struct sockaddr_in sin;
    socklen_t slen = sizeof(sin);
    int status;

    ssock = server_sock();
    signal(SIGCHLD, reaper);
    if ((pid = fork()) == -1)
    sysabort("server/fork");
    if (pid) {
    
    if ((csock = accept(ssock, (struct sockaddr *)&sin, &slen)) == -1)
        sysabort("server/accept");
    total_bytes = 0;
    while ((len = read(csock, buf, sizeof(buf))) > 0) {
        if (sigchld) myabort("server/sigchld");
        offset = buf;
        total_bytes += len;
        while (len > 0) {
        if ((nwritten = write(csock, offset, len)) == -1)
            sysabort("server/write");
        offset += nwritten;
        len -= nwritten;
        }
    }
    if (len == -1)
        sysabort("server/read");
    close(csock);
    fprintf(stdout, "server processed %d bytes\n", total_bytes);
    } else {
    
    echo_client(n, get_port(ssock));
    }
    wait(&status);
}

int
main(int argc, char *argv[]) {
    echo_server((argc == 2) ? atoi(argv[1]) : 1);
    return(0);
}
echo.ocaml
(*
 * $Id: echo.ocaml,v 1.8 2001/05/13 17:13:06 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 * with help from Markus Mottl
 *)

open Unix

let data = "Hello there sailor\n"

let rec sock_write sock buf offset len = 
  if len > 0 then begin 
    let nwritten = write sock buf offset len in 
    sock_write sock buf (offset + nwritten) (len - nwritten) 
  end

let sock_readline buf sock =
  let offset = ref (read sock buf 0 64) in
  while String.get buf (!offset - 1) <> '\n' do
    offset := !offset + (read sock buf !offset 64)
  done;
  !offset

let rec buf_ok buf n = n <= 0 || buf.[n] = data.[n] && buf_ok buf (n - 1)

let echo_client n port =
  let sock = socket PF_INET SOCK_STREAM 0 in
  connect sock (ADDR_INET (inet_addr_of_string "127.0.0.1", port));
  let len = String.length data
  and buf = String.create 64 in
  for i = 1 to n do
    sock_write sock data 0 len;
    let ans_len = sock_readline buf sock in
    if ans_len <> len || not (buf_ok buf (len - 1)) then begin
      prerr_string "client got bad data: ";
      prerr_endline (String.sub buf 0 ans_len);
      exit 1
    end
  done;
  close sock

let ssock =
  let ssock = socket PF_INET SOCK_STREAM 0
  and addr = inet_addr_of_string "127.0.0.1" in
  bind ssock (ADDR_INET (addr, 0));
  setsockopt ssock SO_REUSEADDR true;
  listen ssock 2;
  ssock

let get_port sock =
  match getsockname sock with
  | ADDR_INET (_, port) -> port
  | ADDR_UNIX _ -> raise (Failure "getsockname")

let echo_server n =
  let port = get_port ssock
  and pid = fork() in
  if pid <> 0 then begin
    
    let csock, addr = accept ssock
    and buf = String.create 64
    and len = ref 0
    and nread = ref 1 in
    while !nread > 0 do
      nread := read csock buf 0 64;
      sock_write csock buf 0 !nread;
      len := !len + !nread
    done;
    ignore (wait ());
    Printf.printf "server processed %d bytes\n" !len end
  else
    
    echo_client n port

let _ =
  let n =
    try int_of_string Sys.argv.(1)
    with Invalid_argument _ -> 1 in
  echo_server n
echo.ocamlb
(*
 * $Id: echo.ocaml,v 1.8 2001/05/13 17:13:06 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 * with help from Markus Mottl
 *)

open Unix

let data = "Hello there sailor\n"

let rec sock_write sock buf offset len = 
  if len > 0 then begin 
    let nwritten = write sock buf offset len in 
    sock_write sock buf (offset + nwritten) (len - nwritten) 
  end

let sock_readline buf sock =
  let offset = ref (read sock buf 0 64) in
  while String.get buf (!offset - 1) <> '\n' do
    offset := !offset + (read sock buf !offset 64)
  done;
  !offset

let rec buf_ok buf n = n <= 0 || buf.[n] = data.[n] && buf_ok buf (n - 1)

let echo_client n port =
  let sock = socket PF_INET SOCK_STREAM 0 in
  connect sock (ADDR_INET (inet_addr_of_string "127.0.0.1", port));
  let len = String.length data
  and buf = String.create 64 in
  for i = 1 to n do
    sock_write sock data 0 len;
    let ans_len = sock_readline buf sock in
    if ans_len <> len || not (buf_ok buf (len - 1)) then begin
      prerr_string "client got bad data: ";
      prerr_endline (String.sub buf 0 ans_len);
      exit 1
    end
  done;
  close sock

let ssock =
  let ssock = socket PF_INET SOCK_STREAM 0
  and addr = inet_addr_of_string "127.0.0.1" in
  bind ssock (ADDR_INET (addr, 0));
  setsockopt ssock SO_REUSEADDR true;
  listen ssock 2;
  ssock

let get_port sock =
  match getsockname sock with
  | ADDR_INET (_, port) -> port
  | ADDR_UNIX _ -> raise (Failure "getsockname")

let echo_server n =
  let port = get_port ssock
  and pid = fork() in
  if pid <> 0 then begin
    
    let csock, addr = accept ssock
    and buf = String.create 64
    and len = ref 0
    and nread = ref 1 in
    while !nread > 0 do
      nread := read csock buf 0 64;
      sock_write csock buf 0 !nread;
      len := !len + !nread
    done;
    ignore (wait ());
    Printf.printf "server processed %d bytes\n" !len end
  else
    
    echo_client n port

let _ =
  let n =
    try int_of_string Sys.argv.(1)
    with Invalid_argument _ -> 1 in
  echo_server n
echo.oz
%%% $Id: echo.oz,v 1.0 2002/11/05 12:26:00 dada Exp $
%%% http://dada.perl.it/shootout/
%%%
%%% contributed by Isaac Gouy

%%  Usage: start from command line with
%%     ozc -x echo.oz -o echo.oz.exe
%%     echo.oz.exe 100000

functor
import System Application Open OS

define

   Data = "Hello there sailor\n"
   

proc {ServerThread Sock SPort Bytes}
      Sock = {New Open.socket server(port:SPort)}
      {ServerLoop Sock 0 Bytes}
      {Sock shutDown(how: [receive send])}{Sock close}
end

proc {ServerLoop Sock Sum Bytes}
   local Message NewSum DR DW CR ST in

         %% low-level Selects seem ~6% faster total
      {Sock getDesc(DR DW)}{OS.readSelect DR}
      {OS.read DR 1024 Message nil CR}
         %% {Sock read(list: Message)} %% normal read

      if Message == nil then %% connection has been closed
     Bytes = Sum
      else
     NewSum = {Length Message} + Sum

     {OS.writeSelect DW}{OS.write DW Message ST}
         %% {Sock write(vs: Message)} %% normal write

     {ServerLoop Sock NewSum Bytes}
      end
   end
end


proc {ClientThread SPort N}
   local Sock in 
      Sock = {New Open.socket client(port:SPort)}
      {ClientLoop Sock N}
      {Sock shutDown(how: [receive send])}{Sock close}
   end
end

proc {ClientLoop Sock N}
   local Message DR DW CR ST in
      if N > 0 then

     {Sock getDesc(DR DW)}
     {OS.writeSelect DW}{OS.write DW Data ST}     
         {OS.readSelect DR}{OS.read DR 1024 Message nil CR}
     
     %% {Sock write(vs: Data)}     %% normal write
         %% {Sock read(list: Message)} %% normal read

     if Message == Data then {ClientLoop Sock N-1} end
      end
   end
end


in
   local Args A1 A2 A3 Socket SPort Bytes ArgList Pid in
      Args = {Application.getArgs plain}

      if {Length Args} == 1 then
         %% We are the server process      

         A3|nil = Args

         thread {ServerThread Socket SPort Bytes} end

         %% Prepare to fork an OS process for the client 
         %%    automatically close cmd.exe
         %%    start echo.oz.exe
         %%    pass a flag indicating the client process
         %%    pass the open server port SPort 
         %%    pass the number of times the client should send the data

         ArgList = ["/C" "echo.oz.exe" "client" {IntToString SPort} A3]
         Pid = {New Open.pipe init(cmd: "cmd.exe" args: ArgList)}

         %% Synchronize with server thread completion and indirectly with
         %% the client process. Wait here until the dataflow variable Bytes 
         %% has been given a value in the server thread. That happens after
         %% the client process closes the socket connection, when the client
         %% process has sent all it's data and received all the replies.
 
         {System.showInfo 'server processed '#{IntToString Bytes}#' bytes'} 

      elseif {Length Args} == 3 then 
         %% We are the client process

         %% Take the flag, server port, times-to-repeat from the args
         %% and use the main thread for the client
         A1|A2|A3|nil = Args
         if A1 == "client" then
            {ClientThread {StringToInt A2} {StringToInt A3}}
         end  
      end
   end
   {Application.exit 0}
end
echo.perl
#!/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();
echo.pike
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: echo.pike,v 1.2 2001/01/03 12:12:52 doug Exp $
// http://www.bagley.org/~doug/shootout/
// based on code from: Per Hedbor

#define DATA "Hello there sailor\n"

void echo_server(Stdio.Port p, int n) {
    Stdio.File f = p->accept();
    int tbytes;
    string q;
    while( (q = f->read( 8192,1  )) && strlen( q ) ) {
    tbytes += strlen(q);
    f->write( q );
    }
    write( "server processed %d bytes\n", tbytes );
}

void echo_client(int p, int n) {
    int i;
    Stdio.File f = Stdio.File();

    f->connect( "localhost", p );
    int s = strlen(DATA);
    for (i=0; i<n; i++) {
    f->write( DATA );
    if(  f->read( s ) != DATA ) {
        werror( "Transfer error at repetition "+i+"\n");
        _exit( 1 );
    }
    }
    f->close();
    _exit( 0 );
}

/* Fork is not really available in a threaded pike. Thus this hack. It
 * assumes the pike binary can be found in your path, and that you have
 * a /usr/bin/env
 */
void start_client( int p, int n )
{
    Process.create_process( ({ "e:/pike/7.2.239/bin/pike.exe", __FILE__,
                   (string)p, (string)n }) );
}

void main(int argc, array argv)
{
    if( argc < 3 )
    {
    int n = max((int)argv[-1],1);
    Stdio.Port p = Stdio.Port( 0 );
    int pno = (int)((p->query_address( )/" ")[1]);
    start_client( pno, n );
    echo_server( p, n );
    } else {
    echo_client( (int)argv[1], (int)argv[2] );
    }
    sleep(1);
}
echo.poplisp
;;; -*- mode: lisp -*-
;;; $Id: echo.cmucl,v 1.1 2001/06/16 02:06:03 doug Exp $
;;; http://www.bagley.org/~doug/shootout/
;;; from Bulent Murtezaogl

(in-package "UNIX")
(defun unix-wait ()
  "Wait for a child to die. We don't care about the status"
  (int-syscall ("wait" (* int)) nil)) ;;  is lisp nil == C NULL ?? Dunno.
(in-package "USER")


(define-condition sigpipe)

(defun ih-sigpipe (signal code scp)
  (declare (ignore signal code scp))
  (signal 'sigpipe))

(defun error-return (str)
  (format *standard-output* "Error: ~s ~%" str)
  (quit))

(defun echo-client (port iter)
  (declare (fixnum iter))
  (let* ((stream (sys:make-fd-stream
          (ext:connect-to-inet-socket "127.0.0.1" port)
          :output t :input t :buffering :line))
     (estr "Hello there sailor
")
       (len (length estr))
       (buffer (make-string len)))
    (dotimes (i iter)
      (declare (fixnum i len) (simple-base-string buffer)
           (inline write-sequence sys:read-n-bytes string=))
      (write-sequence estr stream :start 0 :end len )
      (sys:read-n-bytes stream buffer 0 len nil)
      (unless (string= estr buffer) 
    (format t "client did not receive what it sent ~%")))))

  (let ((lsock (ext:create-inet-listener 0))
    (n (parse-integer (or (car pop11::poparglist) "1"))))
    (multiple-value-bind (host port) (get-socket-host-and-port lsock)
      (declare (ignore host))
      (let ((fork-res (unix:unix-fork)))
    (if fork-res
        (if (zerop fork-res)
        (echo-client port n)
          (let ((stream (sys:make-fd-stream
                 (ext:accept-tcp-connection lsock)
                 :output t :input t :buffering :line))
            (buffer (make-string 64))
            (insize 0)
            (sum 0))
        (declare (fixnum insize sum))
        (sys:enable-interrupt UNIX:sigpipe #'ih-sigpipe)
        (handler-case
            (progn
              (loop ;; loop seems to chew up my declarations!?
            while (not (zerop (setf (the fixnum insize)
                        (the fixnum (sys:read-n-bytes stream buffer 0 64 nil)))))
            do (write-sequence buffer stream :start 0 :end insize)
            (incf sum insize))
              (unix::unix-wait)
              (format t "server processed ~D bytes~%" sum))
          (sigpipe (foo) (declare (ignore foo)) (error-return "Kid died prematurely")) ;; as good as catching sigchild for this app 
          (end-of-file (foo) (declare (ignore foo))(error-return "EOF signalled.  Huh???")))))))))
echo.python
#!/usr/local/bin/python
# $Id: echo.python,v 1.7 2001/05/06 22:21:26 doug Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Brad Knotwell

import sys, os
from socket import *

DATA = "Hello there sailor\n"
bufferSize = len(DATA)

def server_sock():
    sock = socket(AF_INET, SOCK_STREAM)
    sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    sock.bind(('127.0.0.1', 0));
    sock.listen(2)
    return(sock)

def get_port(sock):
    host, port = sock.getsockname()
    return(port)

def client_sock(port):
    sock = socket(AF_INET, SOCK_STREAM)
    sock.connect(('127.0.0.1', port))
    return(sock)

def echo_client(n, port):
    sock = client_sock(port)
    sender,receiver = sock.send,sock.recv
    for i in range(0,n):
        sender(DATA)
        ans = receiver(bufferSize)
        while ans[-1] != "\n":
            ans += receiver(bufferSize - len(ans))
        if ans <> DATA:
            raise("client: \"%s\" ne \"%s\"" % (DATA, ans))
    sock.close()

def echo_server(n):
    ssock = server_sock()
    if os.fork() > 0:
        # parent is server
        csock, addr = ssock.accept()
        n = 0
        sender,receiver = csock.send,csock.recv
        while 1:
            dat = receiver(bufferSize)
            if not dat: break
            sender(dat)
            n += len(dat)
        print "server processed %d bytes" % n
        os.wait()
    else:
        # child is client
        echo_client(n, get_port(ssock))

def main():
    n = int(sys.argv[1])
    if n < 1:
        n = 1
    echo_server(n)

main()
echo.ruby
#!/usr/local/bin/ruby
# -*- mode: ruby -*-
# $Id: echo.ruby,v 1.3 2001/05/08 08:08:41 doug Exp $
# http://www.bagley.org/~doug/shootout/

require "socket"

DATA = "Hello there sailor\n"

def echo_client(n, port)
    sock = TCPsocket.open('127.0.0.1', port)
    n.times do
    sock.write(DATA)
    ans = sock.readline
    if ans != DATA then
        raise sprintf("client: \"%s\" \"%s\"", DATA, ans)
    end
    end
    sock.close
end


def echo_server(n)
    ssock = TCPserver.open('127.0.0.1', 0)
    port = ssock.addr[1]
    if pid = fork then
    # parent is server
    csock = ssock.accept
    n = 0
    while str = csock.gets
        n += csock.write(str)
    end
    Process.wait
        printf "server processed %d bytes\n", n
    else
    # child is client
    echo_client(n, port)
    end
end

echo_server(Integer(ARGV.shift || 1))
echo.smlnj
(* -*- mode: sml -*-
 * $Id: echo.smlnj,v 1.1 2001/07/10 00:47:14 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 * from Daniel Wang
 *)
structure Test : sig
 val main : (string * string list) -> OS.Process.status
end =     
 struct        
   exception Error of string
    
   val data = "Hello there sailor\n"

   fun mkSocks () = let
     val server = INetSock.TCP.socket()
     val client = INetSock.TCP.socket()
     val _ = Socket.bind(server,INetSock.any 0)
     val saddr = INetSock.fromAddr(Socket.Ctl.getSockName server)
     val _ = Socket.listen(server,2)
     val _ = Socket.connect(client,INetSock.toAddr saddr)
     val _ = INetSock.TCP.setNODELAY(server,true)
     val _ = INetSock.TCP.setNODELAY(client,true)
   in {client=client,server=server}
   end

   fun readString (s,n) = let
     fun loop(0) = []
       | loop(n) = let
       val data = Byte.bytesToString(Socket.recvVec(s,n))
       val len = String.size data
     in if len = 0 then []
        else (data::(loop(n - len)))
     end
   in String.concat (loop n)
   end
 
   fun writeString (out,str) = 
     Socket.sendVec(out,{buf=Byte.stringToBytes str,i=0,sz=NONE})

   fun closeSock s =
     (Socket.shutdown(s,Socket.NO_RECVS_OR_SENDS);
      Socket.close s)

  fun main (_,args) = let
    val num =
      case args of
    nil => 1
      | n::_ => valOf (Int.fromString n)
    val {client=client_sock,server=server_sock} = mkSocks()
    fun server () = let
      val (sock,_) = Socket.accept(server_sock)
      fun s b = 
    case readString(sock,19) of
       "" => (Posix.Process.wait ();
          TextIO.output(TextIO.stdOut,
                concat ["server processed ",
                    Int.toString b,
                    " bytes\n"]);
          TextIO.flushOut(TextIO.stdOut))
     | i =>(writeString(sock,i);
        s (b + 19))
    in s 0
    end
    fun client () = let
      fun c 0 = closeSock(client_sock)
    | c n = let
        val _ = writeString(client_sock,data);
        val reply = readString(client_sock,19)
      in if reply = data then c(n - 1)
         else raise Error "Didn't receive the same data"
      end
    in c num
    end
  in
    case Posix.Process.fork () of
      SOME pid => server ()
    | NONE => client ();
     OS.Process.success
  end 
end

val _ = SMLofNJ.exportFn("echo",Test.main);
echo.tcl
#!/usr/local/bin/tclsh
# $Id: echo.tcl,v 1.1 2001/03/02 04:05:06 doug Exp $
# http://www.bagley.org/~doug/shootout/

# from: Kristoffer Lawson

proc newClient {sock addr port} {
    fconfigure $sock -buffering line
    set r [gets $sock]
    set rLength 0
    while {![eof $sock]} {
    incr rLength [string length $r]
    # Extra increase because [gets] doesn't return \n
    incr rLength
    puts $sock $r
    set r [gets $sock]
    }
    puts "server processed $rLength bytes"
    exit
}


proc runClient {n addr port} {
    set sock [socket $addr $port]
    fconfigure $sock -buffering line
    set msg "Hello there sailor"

    while {$n} {
    puts $sock $msg
    if {[gets $sock] != $msg} {
        error "Received different message: $r."
    }
    incr n -1
    }
}


set n [lindex $argv 0]

if {[llength $argv] < 2} {
    socket -server newClient 10000
    exec tclsh83 [info script] $n client &
    vwait forever
} else {
    runClient $n localhost 10000
}