java.net

https://docs.oracle.com/javase/tutorial/networking/overview/networking

Networking

Protocols for the internet: TCP, UDP

Transmission Control Protocol TCP

URL, URLConnection, Socket, ServerSocket

Connection based.

Point 2 Point channel for applications like HTTP, FTP, ...

User Datagram Protocol UDP

DatagramPacket, DatagramSocket, MulticastSocket

Not connection based.

Sends independent data packets (datagrams).

No guarantees about arrival.

Messages independent of eachother.

Contain port + data.

Ports [0 - 65535]

A computer has one physical connection to the network.

Computer identified by its IP address (32bit)

IP protocol uses IP address to deliver data to right computer.

Ports (16bit) determine which process on the computer the data is meant for.

Port numbers [0 - 1023] are called "well-known" and are restricted for ie. HTTP, FTP.

URL Connection

URL

httpsundefinedProtocol://example.comundefinedHostName:433undefinedPort/peopleundefinedPath?name=mauroundefinedQueryString#aboutundefinedFragment\textcolor{grey}{ \underbrace{\textcolor{white}{\texttt{https}}}_{\textsf{Protocol}} \textcolor{white}{\texttt{://}} \underbrace{\textcolor{white}{\texttt{example.com}}}_{\textsf{Host Name}} ~\textcolor{white}{ \texttt{:}} ~ \underbrace{\textcolor{white}{\textcolor{white}{\textsf{433}}}}_{\textsf{Port}} ~ \textcolor{white}{ \texttt{/}} ~ \underbrace{\textcolor{white}{\texttt{people}}}_{\textsf{Path}} ~ \textcolor{white}{ \texttt{?}} ~ \underbrace{\textcolor{white}{\texttt{name = mauro}}}_{\textsf{Query String}} ~\textcolor{white}{ \texttt{\#}} ~ \underbrace{\textcolor{white}{\texttt{about}}}_{\textsf{Fragment}} }Protocolhttps​​://Host Nameexample.com​​:Port433​​/Pathpeople​​?Query Stringname = mauro​​#Fragmentabout​​

use URL Object to create URL

URL myURL = new URL("http://example.com/");

use .openStream() to read content

returns an InputStream object

URLConnection

use .openConnection() on URL to create connection with chosen protocol

returns java.net.HttpURLConnection(specific subclass for HTTP)

you can then call .connect() on that connection

Reading:

import java.net.*;
import java.io.*;public class URLConnectionReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("http://www.example.com/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}

Writing:

import java.io.*;
import java.net.*;public class Reverse {
public static void main(String[] args) throws Exception {//read args
URL url = new URL(args[0]);
String stringToReverse = URLEncoder.encode(args[1], "UTF-8");URLConnection connection = url.openConnection();
connection.setDoOutput(true);//send string to server
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream());
out.write("string=" + stringToReverse);
out.close();BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
String decodedString;//read server response
while ((decodedString = in.readLine()) != null) {
System.out.println("server response: " + decodedString);
}
in.close();
}
}

Sockets

For TCP, a connection must first be established between client and server.

Server is listening for requests on specified port.

Client requests connection (to hostname and port).

Server accepts connection, opens a new socket for that port (for other clients).

Server sets its own remote endpoint to port of client (client doesnt decline).

Connection established.

Endpoint

IP address + port number

Socket

A socket is one endpoint of a two-way communication link between two programs running on the network.

A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to.

java.net.Socket

Socket for Cient program.

Example: Echo Server

Connects to an echo server.

Server receives data and echoes it back.

import java.io.*;
import java.net.*;public class EchoClient {
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.err.println(
"Usage: java EchoClient <host name> <port number>");
System.exit(1);
}//read input
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);try ( //try-with-resources -> automatically closes streams
Socket echoSocket = new Socket(hostName, portNumber);
//Server
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true); //autoflush
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));//System
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
) {
String userInput;
while ((userInput = stdIn.readLine()) != null) { //read from terminal
out.println(userInput); //send to server
System.out.println("echo: " + in.readLine()); //show response
}} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}

java.net.ServerSocket

Socket for Server program

Server runs has a socket with a port number and listens for requests.

Example: KnockKnock Client + Server

import java.io.*;
import java.net.*;public class KnockKnockClient {
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.err.println(
"Usage: java EchoClient <host name> <port number>");
System.exit(1);
}String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);try (
Socket kkSocket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;//wait for server response
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("Bye."))
break;
//wait for user input
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser); //send input to server
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
import java.net.*;
import java.io.*;public class KnockKnockServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java KnockKnockServer <port number>");
System.exit(1);
}int portNumber = Integer.parseInt(args[0]);try (
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine, outputLine;
// Initiate conversation with client
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);//repeat until output is Bye
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
import java.net.*;
import java.io.*;public class KnockKnockProtocol {
private static final int WAITING = 0;
private static final int SENTKNOCKKNOCK = 1;
private static final int SENTCLUE = 2;
private static final int ANOTHER = 3;private static final int NUMJOKES = 5;private int state = WAITING;
private int currentJoke = 0;private String[] clues = { "Turnip", "Little Old Lady", "Atch", "Who", "Who" };
private String[] answers = { "Turnip the heat, it's cold in here!",
"I didn't know you could yodel!",
"Bless you!",
"Is there an owl in here?",
"Is there an echo in here?" };//returns output for given input
public String processInput(String theInput) {
String theOutput = null;if (state == WAITING) {
theOutput = "Knock! Knock!";
state = SENTKNOCKKNOCK;
} else if (state == SENTKNOCKKNOCK) {
if (theInput.equalsIgnoreCase("Who's there?")) {
theOutput = clues[currentJoke];
state = SENTCLUE;
} else {
theOutput = "You're supposed to say \"Who's there?\"! " +
"Try again. Knock! Knock!";
}
} else if (state == SENTCLUE) {
if (theInput.equalsIgnoreCase(clues[currentJoke] + " who?")) {
theOutput = answers[currentJoke] + " Want another? (y/n)";
state = ANOTHER;
} else {
theOutput = "You're supposed to say \"" +
clues[currentJoke] +
" who?\"" +
"! Try again. Knock! Knock!";
state = SENTKNOCKKNOCK;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
theOutput = "Knock! Knock!";
if (currentJoke == (NUMJOKES - 1))
currentJoke = 0;
else
currentJoke++;
state = SENTKNOCKKNOCK;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}

Multiple Clients

In the previous example - the server socket gets binded to the client socket and other clients wont get accepted.

We want multiple clients to come into the same port, queue them there and use multithreading.

KKMultiServer loops forever:

while (true) {
listen for requests;
accept a connection;
create a new KKMultiServerThread thread to deal with the client;
}

import java.net.*;
import java.io.*;public class KKMultiServer {
public static void main(String[] args) throws IOException {if (args.length != 1) {
System.err.println("Usage: java KKMultiServer <port number>");
System.exit(1);
}int portNumber = Integer.parseInt(args[0]);
boolean listening = true;try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
new KKMultiServerThread(serverSocket.accept()).start(); //start thread
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
import java.net.*;
import java.io.*;public class KKMultiServerThread extends Thread {
private Socket socket = null;public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread"); //call constructor of parent
this.socket = socket;
}
public void run() {try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Datagrams

Packages are sent without a connection.

No guarantee for arrival.

No order of arrival.

DatagramPacket

DatagramSocket

Receives Packets.

MulticastSocket

DatagramPacket can be broadcasted to multiple recipients with MulticastSockets.

import java.io.*;public class QuoteServer {
public static void main(String[] args) throws IOException {
new QuoteServerThread().start();
}
}
import java.io.*;
import java.net.*;
import java.util.*;public class QuoteClient {
public static void main(String[] args) throws IOException {if (args.length != 1) {
System.out.println("Usage: java QuoteClient <hostname>");
return;
}DatagramSocket socket = new DatagramSocket();// send request
byte[] buf = new byte[256];
InetAddress address = InetAddress.getByName(args[0]);
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
socket.send(packet);
// get response
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);// display response
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Quote of the Moment: " + received);
socket.close();
}
}

When a client sends a DataPacket to the Server, that means its requesting a quote.

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;public class QuoteServerThread extends Thread {protected DatagramSocket socket = null; //quotes to send
protected BufferedReader in = null; //quotes from file
protected boolean moreQuotes = true;public QuoteServerThread() throws IOException {
this("QuoteServerThread");
}public QuoteServerThread(String name) throws IOException {
super(name);
socket = new DatagramSocket(4445);try {
in = new BufferedReader(new FileReader("one-liners.txt"));
} catch (FileNotFoundException e) {
System.err.println("Could not open quote file. Serving time instead.");
}
}public void run() {while (moreQuotes) {
try {
byte[] buf = new byte[256];// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); //content not read// figure out response
String dString = null;
if (in == null) {
dString = new Date().toString();
} else {
dString = getNextQuote();
}buf = dString.getBytes();// send the response to the client at "address" and "port"
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);} catch (IOException e) {
e.printStackTrace();
moreQuotes = false;
}
}
socket.close();
}protected String getNextQuote() {
String returnValue = null;
try {
if ((returnValue = in.readLine()) == null) {
in.close();
moreQuotes = false;
returnValue = "No more quotes. Goodbye.";
}
} catch (IOException e) {
returnValue = "IOException occurred in server.";
}
return returnValue;
}
}