Networking (UDP / TCP)
UDP: Greeting Server (1 session)
In this session, we you will explore the API for receiving and sending UDP message in Java.
Reference Code & Quiz
You are given the following example code that both send and receive UDP messages.
import java.io.IOException;
import java.net.*;
public class Net {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(4445);
boolean running = true;
byte[] buf = new byte[256];
while (running) {
DatagramPacket inPacket = new DatagramPacket(buf, buf.length);
socket.receive(inPacket);
String received = new String(inPacket.getData(), 0, inPacket.getLength());
System.out.println("Received: " + received);
if (received.equals("end")) {
running = false;
continue;
}
InetAddress senderAddress = inPacket.getAddress();
int senderPort = inPacket.getPort();
DatagramPacket outPacket = new DatagramPacket(buf, buf.length, senderAddress, senderPort);
socket.send(outPacket);
}
socket.close();
}
}
- Reference (javadoc):
DatagramSocket
DatagramPacket
- XXXX: GIYF (google: XXXX javadoc 17)
By analyzing the code sample above, answer all the following questions:
Reception:
- Which lines are responsible for receiving messages?
- On which port is the server listening?
- What is the maximum size of a received message?
- What does the server do when a message is received?
Sending:
- What are the lines responsible for sending messages?
- What is the content of the message sent?
- Where is the message sent? (which address and port)
Miscellaneous:
- What class represents an IP adress?
- Under which conditions does the program terminates?
- What are the blocking operations in this code?
Hands-On exercises
Exercise: Write a Java program that:
- listens on a given port for incoming UDP connections
- when receiving the message "XXXX" prints "Greetings, XXXXX" on the standard output (i.e. in the terminal where the server is running)
For testing your program, you can use the following command to send UPD message to a given port (here 1789). Note that this will only work on linux.
# Send a UPD message (here "Alice"), on a given port (here 1789)
# on a given address (here localhost: 127.0.0.1)
echo -n "Alice" > /dev/udp/127.0.0.1/1789
Exercise: Instead of using the command line, create a new Java program that sends a message to the server. Note that you can construct an InetAddress
from a string with the InetAddress.getByName()
method (e.g. InetAddress.getByName("127.0.0.1")
).
Exercise: Now we will combine all the code you have written into a single program.
- Adapt your server side code (the one that listens for new UDP messages) so that it is implemented in a
GreeterServer
class that extendsThread
(therun()
method of the thread should execute the server) - in the same program, create a
sendName(String name)
method that send a nameString
to the server (essentially doing the same as your client code from earlier) - In the
main
method, start a greeter server thread - In the same
main
, use thesendName
method to send several messages to the server.
Exercise: In addition to the name of the person, print the IP address from where the message was sent. Check that this work by sending a message from another machine (suggestion: use SSH and the echo
command above)
TCP (1 session)
Your objective in this session is to write an averaging service over TCP.
In a nutshell, it means that you will have a server running to which any user can connect. Once a user is connected, it may start sending numbers (integers) to the server. Each time the user sends a new number, the server must answer with the average of the number received so far from this user.
Example of what a session should look like:
Welcome to the averaging client.
Please enter the next number.
> 6
Sending to server awaiting response...
Received current average: 6.0 (computed on our HPC cluster)
Please enter the next number.
> 9
Sending to server awaiting response...
Received current average: 7.5 (computed on our HPC cluster)
Note that:
- multiple users must be able to connect to your server at the same time
- you must not mix the numbers of two users
Ready? Code! (but you may want to look at the resources below ;)
Useful Resources for this exercise
The tutorial below introduces all concepts that are useful for you to know for this exercise. Take the time to read it carefully.
Reading/Writing Data to Streams
The Java standard library provides abstractions for input/output with two main classes:
InputStream
: anything you can read from (standard input, files, incoming sockets, ...)OutputStream
: anything you can write to (standard output, files, outgoing sockets, ...)
These two classes are fairly low-level and allow you to read/write bytes. Since this is usually to low-level, the standard library provides many wrappers around those classes that extend their capabilities.
In particular, useful for today's exercise are the DataOutputStream
and DataInputStream
classes. When wrapping the input/output streams of a socket, they allow you to transfer common java primitives (ints, doubles, ...).
Below are two examples for reading/writing double to sockets.
static void writeDoubleToSocket(Socket socket, double number) throws IOException {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeDouble(number);
}
static double readDoubleFromSocket(Socket socket) throws IOException {
DataInputStream in = new DataInputStream(socket.getInputStream());
return in.readDouble();
}
Reading from standard input
Below is an example code that reads an integer from the console (standard input). In Java, the standard input is accessible through the System.in
object (of type... InputStream
).
/** Reads an integer from the standard input and returns it.
*
* If the user enters an invalid text, he will be prompted to retry.
*/
static int readIntFromConsole() throws IOException {
// System.in is an InputStream which we wrap into the more capable BufferedReader
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String input = reader.readLine();
try {
int n = Integer.parseInt(input);
return n;
} catch (NumberFormatException e) {
System.out.print("Not an integer, try again: ");
}
}
}