<commit_before># Echo Client & Server <!-- omit in toc -->

- [Overview](#overview)
- [Socket resources](#socket-resources)
- [The echo client/server](#the-echo-clientserver)
- [How does all this end?](#how-does-all-this-end)
- [Bats testing](#bats-testing)
- [Manual testing](#manual-testing)
  - [Testing your server](#testing-your-server)
  - [Testing your client](#testing-your-client)
- [To Do](#to-do)

## Overview

This lab explores the idea of client-server organization.  In a client-server
configuration one central machine called the **server** acts as the source
for some resource or service.  Other machines known as **clients** utilize the
resource or service provided by the server.  A good example would be a web-server
providing web-pages to multiple browsers on multiple computers.

(Note that the "server" could actually be a whole cluster of (virtual)
machines that collectively provide the desired service. Such clusters are
often configured so there is a single domain name or IP address that clients
use, so it still looks to them like there's a single machine providing the
service.)

The term **client-server** refers to the configuration of the service provider and
service consumer.  It does not require multiple machines. It is possible for the same
computer to act as server and as client.

In this lab we'll use Java implement a simple, socket-based client-server
system (the echo client and server). In development you'll likely just run
both the client and server code on the same machine, but you (fairly easily)
run them on different machines if you want to see that "in action".

A _socket_ is a common networking tool that provides two-way communication
between a pair of (not necessarily distinct) computers. Each computer has the
ability to write data (ultimately a stream of bytes) _to_ the socket on their
end, and read data (also a sequence of bytes) _from_ the socket. See the figure
below for an example of socket communication.

One of the big wins of using sockets (even for communication within a single
machine) is that the code for the client and server can be written entirely
independently, as long as the calling structure (the API, essentially) has been
agreed upon. It is often the case, for example, that the client and server are
written in different languages, e.g., JavaScript in the browser for the client,
and Java or Rust for the server.

Raw socket programming can actually be quite tricky. Luckily most modern
languages (including Java) provide nice socket libraries that abstract away
a lot of the underlying details and allow us to just treat a socket as a
pair of streams: An _input stream_ for reading from the socket, and an _output
stream_ for writing to the socket.

## Socket resources

You might find it useful to review and run this
[Date Server example](https://gist.github.com/NicMcPhee/2060037163d0d7fb475b5e4395b9ec32).
This sample program does many (but
not all) of the important things (including the socket work). The one
big difference there is that the `DateServer` returns a single string
and quits, where the `EchoServer` should continue to echo back its input.
That said, the socket work in this example should be helpful.

[The Java "All About Sockets" tutorial](https://docs.oracle.com/javase/tutorial/networking/sockets/index.html)
covers all the key pieces for this
lab. There's a warning at the top about it being written for Java 8, but
nothing has changed in the socket libraries since then that would affect
this lab.

## The echo client/server

Both as a way of gaining some experience with socket programming and as
example of building both ends of a client/server system, we'll build
what's called an *echo server*. An echo server is a server that echoes
back whatever it receives from a client. The starter code and tests are
in this Github repo.

Your server should wait for a client
connection on the port specified by the instructor using `Socket.accept()`.
When a connection is made, the server should repeatedly:

- Read some data from the socket<commit_msg>Add note the reviewing the JavaDoc API info<commit_after># Echo Client & Server <!-- omit in toc -->

- [Overview](#overview)
- [Socket resources](#socket-resources)
- [The echo client/server](#the-echo-clientserver)
- [How does all this end?](#how-does-all-this-end)
- [Bats testing](#bats-testing)
- [Manual testing](#manual-testing)
  - [Testing your server](#testing-your-server)
  - [Testing your client](#testing-your-client)
- [To Do](#to-do)

## Overview

This lab explores the idea of client-server organization.  In a client-server
configuration one central machine called the **server** acts as the source
for some resource or service.  Other machines known as **clients** utilize the
resource or service provided by the server.  A good example would be a web-server
providing web-pages to multiple browsers on multiple computers.

(Note that the "server" could actually be a whole cluster of (virtual)
machines that collectively provide the desired service. Such clusters are
often configured so there is a single domain name or IP address that clients
use, so it still looks to them like there's a single machine providing the
service.)

The term **client-server** refers to the configuration of the service provider and
service consumer.  It does not require multiple machines. It is possible for the same
computer to act as server and as client.

In this lab we'll use Java implement a simple, socket-based client-server
system (the echo client and server). In development you'll likely just run
both the client and server code on the same machine, but you (fairly easily)
run them on different machines if you want to see that "in action".

A _socket_ is a common networking tool that provides two-way communication
between a pair of (not necessarily distinct) computers. Each computer has the
ability to write data (ultimately a stream of bytes) _to_ the socket on their
end, and read data (also a sequence of bytes) _from_ the socket. See the figure
below for an example of socket communication.

One of the big wins of using sockets (even for communication within a single
machine) is that the code for the client and server can be written entirely
independently, as long as the calling structure (the API, essentially) has been
agreed upon. It is often the case, for example, that the client and server are
written in different languages, e.g., JavaScript in the browser for the client,
and Java or Rust for the server.

Raw socket programming can actually be quite tricky. Luckily most modern
languages (including Java) provide nice socket libraries that abstract away
a lot of the underlying details and allow us to just treat a socket as a
pair of streams: An _input stream_ for reading from the socket, and an _output
stream_ for writing to the socket.

## Socket resources

You might find it useful to review and run this
[Date Server example](https://gist.github.com/NicMcPhee/2060037163d0d7fb475b5e4395b9ec32).
This sample program does many (but
not all) of the important things (including the socket work). The one
big difference there is that the `DateServer` returns a single string
and quits, where the `EchoServer` should continue to echo back its input.
That said, the socket work in this example should be helpful.

[The Java "All About Sockets" tutorial](https://docs.oracle.com/javase/tutorial/networking/sockets/index.html)
covers all the key pieces for this
lab. There's a warning at the top about it being written for Java 8, but
nothing has changed in the socket libraries since then that would affect
this lab.

You probably want to review the API docs for the relevant Java classes
(e.g., `Socket` and `ServerSocket`, but also perhaps `InputStream` and
`OutputStream`).

## The echo client/server

Both as a way of gaining some experience with socket programming and as
example of building both ends of a client/server system, we'll build
what's called an *echo server*. An echo server is a server that echoes
back whatever it receives from a client. The starter code and tests are
in this Github repo.

Your server should wait for a client
connection on the port specified by the instructor using `Socket.accept()`.
When a connection is made, the server should repeatedly:

- Read some data from the socket
{'fraction_non_alphanumeric': 0.0578960038517092, 'fraction_numerical': 0.005777563793933558, 'mean_word_length': 4.52093023255814, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '35979', 'n_tokens_mistral': 2152, 'n_tokens_neox': 2045, 'n_words': 1249}