Lecture 21 Sockets 1 (Not in D&D) Date
Goals By the end of this lesson, you should: Understand the difference in the role of a server and client on a network. Be able to configure a server socket and a client socket in Java. Understand the basics of a TCP connection from an application point of view. Be able to implement a simple server and client program to exchange text-based information via a network such as the Internet.
Terminology Terminology Java Sockets Simple Client Simple Server Notes Summary On a TCP/IP based network such as the Internet, each machine is known as a host. Think of it as a building. A host may have one or more network interfaces. Note that these have nothing to do with the Java interface concept. These are interfaces such as Ethernet interfaces or WiFi. Think of them as entrances to the building. Each network interface has an IP address (usually IP version 4 but increasingly IPv6 as well). IPv4 addresses are 4 integers between 0 and 255 separated by dots, e.g., 130.216.159.127. Think of them as the “street address” of the building. Each host can run multiple applications that use the network. Applications come in two flavours: servers and clients.
Terminology Terminology Java Sockets Simple Client Simple Server Notes Summary A server is an application on a host that waits for incoming connection requests from a client. Example: A web server waits for incoming connections from browser clients. A client is an application on (usually a different host) that initiates the connection to a server. Example: A web browser is a client program that initiates connections to web servers. On the network, data travels in packets, a kind of serialized object. Think of them as snail mail. Each packet carries an IP header that identifies source and destination hosts (via their IP addresses). TCP packets travel inside the payload of IP packets.
Terminology Terminology Java Sockets Simple Client Simple Server Notes Summary To find out which application the payload of a TCP packet is intended for, each TCP packet carries a TCP header with the port numbers of the sending and the destination application. Port numbers are integers between 1 and 65535. Think of them as the apartment numbers of the actual sender & receiver in the building. A server binds to a particular port number and listens on that port. This port number must be known to any client wanting to connect to the server. A client connects to the server address/port using its own address and an arbitrary port supplied by the client’s operating system. To do so, it sends a TCP connection request.
Terminology Terminology Java Sockets Simple Client Simple Server Notes Summary The listening server decides whether to accept the connection request. Once accepted, both sides can send and receive data on the connection. The data streams in each direction are reliable byte streams, meaning either side can be assured that data it sends will be received in the order it was sent. Either server or client may close the connection.
Sockets Terminology Java Sockets Simple Client Simple Server Notes Summary In order to communicate via TCP connections, applications use data structures called sockets. Java knows two types of sockets: Sockets of the Socket class. We instantiate a Socket object by passing the Socket() constructor an IP address and port number to connect to. The constructor either establishes the connection and returns a Socket object, or throws an IOException if it is unable to connect (e.g., network problem, server (host or application) not running). Sockets of the ServerSocket class. We instantiate a ServerSocket by passing its constructor a port number to bind to and listen on. We also specify a maximum number of connections that are allowed to wait for acceptance.
ServerSockets Terminology Java Sockets Simple Client Simple Server Notes Summary A ServerSocket throws an IOException if it is unable to bind to the specified port. This usually happens if the port is already in use (something that often happens during development!) Once the ServerSocket listens, we call its accept() method. This method blocks (does not return) until there is a connection request from a client. The method returns an already-connected Socket object.
Connected Sockets Terminology Java Sockets Simple Client Simple Server Notes Summary Once both sides have a connected Socket object, they can communicate with each other. Each side can find out who the remote side is by calling the getRemoteSocketAddress() method on its own socket. This returns the IP address and port number used by the socket on the other side. On each socket, we can get an InputStream (for reading data from the other side) with its getInputStream() method. We can use this stream with Scanner, ObjectInputStream, DataInputStream etc. Similarly, we can get an OutputStream (for writing data to the other side) with getOutputStream(). We can use this stream with PrintStream, Formatter, ObjectOutputStream, DataOutputStream etc.
Example: Simple Client Terminology Java Sockets Simple Client Simple Server Notes Summary import java.net.Socket; import java.io.PrintStream; import java.util.Scanner; public class SimpleClient { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // IP address and port to connect to: String serverHost = "localhost"; int serverPort = 9876; Socket socket = null; try { socket = new Socket(serverHost, serverPort); } catch (Exception e1) { System.err.print("Unable to connect to " + serverHost); System.err.println(" on " + serverPort); System.err.println(e1.getMessage()); System.exit(1); } System.out.print("Connected to " + serverHost); System.out.println(" on port " + serverPort); …
Example: Simple Client Terminology Java Sockets Simple Client Simple Server Notes Summary … try { Scanner input = new Scanner(socket.getInputStream()); PrintStream output = new PrintStream(socket.getOutputStream()); String message = ""; while (!message.trim().equals("quit")) { System.out.println("Enter a string to send to the server:"); message = scanner.nextLine(); output.println(message); System.out.println("Done. Waiting for server response."); String response = input.nextLine(); System.out.print("The server responded with a "); System.out.println(response.length() + " byte message: "); System.out.println("\"" + response.trim() + "\""); } System.out.println("Disconnecting from " + serverHost); socket.close(); System.out.print("Done."); } catch (Exception e2) { System.err.print("Something went wrong with the socket communication."); System.err.println(e2.getMessage()); System.exit(1);
Example: Simple Server Terminology Java Sockets Simple Client Simple Server Notes Summary import java.net.ServerSocket; import java.net.Socket; import java.io.IOException; import java.io.PrintStream; import java.util.Scanner; public class SimpleServer { public static void main(String[] args) { // Some configuration int port = 9876; // port number between 1024 and 65535 int backlog = 1; // allow 1 pending connection request // Try to create a server socket for the given port ServerSocket server = null; try { server = new ServerSocket(port, backlog); } catch (IOException ioExc1) { System.err.println(“Can’t create server socket"); System.err.println(ioExc1.getMessage()); System.exit(1); …
Example: Simple Server Terminology Java Sockets Simple Client Simple Server Notes Summary … Socket socket = null; // ...only null for now while (true) { try { // accept() waits for an incoming connection socket = server.accept(); System.out.println("Accepted connection from client " + socket.getRemoteSocketAddress()); // Let's communicate: String inputString = ""; Scanner input = new Scanner(socket.getInputStream()); // output PrintStream lets us send data to the server PrintStream output = new PrintStream(socket.getOutputStream()); // Now communicate until the client sends "quit": while (!inputString.trim().equals("quit")) { inputString = input.nextLine(); // Communication here just means echoing the // client input back: System.out.println("Client says: " + inputString); String outputString = "You said: " + inputString + "\n"; output.println(outputString); } …
Example: Simple Server Terminology Java Sockets Simple Client Simple Server Notes Summary … try { … catch (IOException ioExc2) { // Ignore and continue System.err.println("Something went wrong with the connection"); System.err.println(ioExc2.getMessage()); } finally { try { // Closing the socket prevents a resource leak if (socket != null) socket.close(); catch (IOException ioExc3) { System.err.println("Couldn't close socket properly, ignoring."); System.err.println(ioExc3.getMessage()); System.out.println("Disconnected from client!"); // Ready for the next connection Proper cleanup is important here as our server might be handling many connections over its lifetime, and sockets are a scarce resource (a system can typically have at most 65536 of them).
Why is this “simple”? Terminology Java Sockets Simple Client Simple Server Notes Summary Note that our simple server doesn’t get to call its accept() method again until it the connection has closed. This means that the simple server can only handle one connection at a time. Most “real” servers need to be able to accept connections pretty much as soon as they come in, and handle them there and then, no matter how long they will last. This is typically done with threads, a concept that we will revisit at length shortly. In the next lecture, we will take a sneak preview at a threaded server application that lets our server take multiple simultaneous client connections.
Note: Trying this out Terminology Java Sockets Simple Client Simple Server Notes Summary The client code example for this lecture uses a hardwired IP address (or rather, a hostname called “localhost”, which your computer knows to translate to IP address 127.0.0.1). This is a special IP address that points back at your own machine. If you want to experiment between different machines, you need to know the IP address of the server and need to change this in the client code. In order to run both client and server on your own machine, you need to run one of them (the server) from a command line window rather than Eclipse. Open a command line window and change to the src directory in your Eclipse. Build the server with: javac SimpleServer.java Then run java SimpleServer and run the client from Eclipse. You can stop the server in the command line window with CTRL+C. If you run the server in Eclipse, you will not be able to start the client there, or re-start the server (unless you restart Eclipse).
What do we know Terminology Java Sockets Simple Client Simple Server Notes Summary Java server sockets are a ServerSocket object. They are configured with a port and a maximum backlog and start to listen upon instantiation. Java client sockets are a Socket object. They are configured with the server address and port to connect to, and attempt to connect on instantiation. They throw an exception if they cannot connect. The server socket waits for an incoming connection when its accept() method is called. The method returns a Socket object for the incoming connection. We can use the input and output streams of the Socket object with our usual stream tools for writing and reading to/from console and file.
Resources Terminology Java Sockets Simple Client Simple Server Notes Summary https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html https://docs.oracle.com/javase/8/docs/api/java/net/ServerSocket.html https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html https://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html
Next Lecture Sockets 2 (not in D&D)