Advanced Socket Programming in Java

222 downloads 6179 Views 557KB Size Report
TCP/IP Protocol suite. •When you write java program that communicate over network you are working at Application Layer. •Typically you donot need to be ...
Advanced Socket Programming in Java

TCP/IP Protocol suite •When you write java program that communicate over network you are working at Application Layer •Typically you donot need to be concerned with TCP/UDP layers

•Instead the classes in java.net package provide system independent network communication •But to understand which java classes a program is using you need to understand the difference between TCP and UDP.

TCP versus UDP • Transmission Control Protocol(TCP) – Set up the Connection first, then Send Data – After Exchanging Data, Need the Procedure for Releasing Connection – Similar to Telephone Communication – High Reliability – High overload to release the connection -> Not efficient for small data

• User Datagram Protocol(UDP) – Without Connection, Split data into Packet with fixed length, Attach address, then transmit them. – Similar to Mail – Low Reliability

TCP/UDP

TCP

UDP

TCP Server Socket • java.net.ServerSocket class • Binds to a local port to listen for initial connections • Can be bound to a local IP for multi-homed machines • accept() method returns a java.net.Socket, not an integer descriptor

TCP Client Socket • java.net.Socket class • Combines socket with socket options (timeout, linger, keep alive, no delay, etc) • Encapsulates a java.io.InputStream and a java.io.OutputStream – can be retrieved for use in a layered I/O system

UDP Socket • java.net.DatagramSocket class • Java makes no distinction between client/server for UDP sockets • Connected mode UDP supported in Java 2 • Can be bound to both a local port & a local IP address – multi-homed support • Supports some socket options (timeout, buffer size)

UDP Datagram • • • • •

java.net.DatagramPacket class Expects a byte array of data Address optional for connected-mode UDP This class is final – can’t be extended! java.net.DatagramSocket instances can only send instances of java.net.DatagramPacket

Socket Programming in java • A socket is an 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 destined to be sent. • Java’s .net package provides two classes: – Socket – for implementing a client – ServerSocket – for implementing a server

Implementing a server socket 1. Open the Server Socket: ServerSocket server; DataOutputStream os; DataInputStream is; server = new ServerSocket( PORT ); 2. Wait for the Client Request: Socket client = server.accept(); 3. Create I/O streams for communicating to the client is = new DataInputStream( client.getInputStream() ); os = new DataOutputStream( client.getOutputStream() ); 4. Perform communication with client Receive from client: String line = is.readLine(); Send to client: os.writeBytes("Hello\n"); 5. Close sockets: client.close(); For multithreaded server: while(true) { i. wait for client requests (step 2 above) ii. create a thread with “client” socket as parameter (the thread creates streams (as in step (3) and does communication as stated in (4). Remove thread once service is provided. }

Implementing a Client 1. Create a Socket Object: client = new Socket( server, port_id ); 2. Create I/O streams for communicating with the server. is = new DataInputStream(client.getInputStream() ); os = new DataOutputStream( client.getOutputStream() );

3. Perform I/O or communication with the server: – Receive data from the server:

String line = is.readLine(); – Send data to the server:

os.writeBytes("Hello\n"); 4. Close the socket when done: client.close();

Socket Classes • Provides interface to TCP, UDP sockets • Socket – TCP client sockets

• ServerSocket – TCP server sockets

• DatagramSocket – UDP sockets (server or client)

Constructors • Socket() − Creates an unconnected socket, with the system-default type of SocketImpl. • Socket(InetAddress address, int port) − Creates a stream socket and connects it to the specified port number at the specified IP address. • Socket(InetAddress address, int port, InetAddress localAddr, int localPort) − Creates a socket and connects it to the specified remote address on the specified remote port. • Socket(SocketImpl impl) − Creates an unconnected Socket with a userspecified SocketImpl. • Socket(String host, int port) − Creates a stream socket and connects it to the specified port number on the named host. • Socket(String host, int port, InetAddress localAddr, int localPort) − Creates a socket and connects it to the specified remote host on the specified remote port.

Socket Methods • • • • • •

getInputStream() getOutputStream() close() getInetAddress() getPort() getLocalPort()

Java.net.ServerSocket class • The java.net.ServerSocket class represents a server socket. • A ServerSocket object is constructed on a particular local port. Then it calls accept() to listen for incoming connections. • accept() blocks until a connection is detected. Then accept() returns a java.net.Socket object that performs the actual communication with the client.

Constructors • There are three constructors that let you specify the port to bind to, the queue length for incoming connections, and the IP address to bind to: public ServerSocket(int port) throws IOException public ServerSocket(int port, int backlog) throws IOException public ServerSocket(int port, int backlog, InetAddress networkInterface) throws IOException

ServerSocket Methods • • • •

accept() close() getInetAddress() getLocalPort()

Setting Server Socket Options • There are three methods to set and get various options. The defaults are generally fine. • public synchronized void setSoTimeout(int timeout) throws SocketException • public synchronized int getSoTimeout() throws IOException • public static synchronized void setSocketFactory(SocketImplFactory fac) throws IOException

ServerSocket & Exceptions • public ServerSocket(int port) throws IOException – Creates a server socket on a specified port. – A port of 0 creates a socket on any free port. You can use getLocalPort() to identify the (assigned) port on which this socket is listening. – The maximum queue length for incoming connection indications (a request to connect) is set to 50. If a connection indication arrives when the queue is full, the connection is refused.

• Throws: – IOException - if an I/O error occurs when opening the socket. – SecurityException - if a security manager exists and its checkListen method doesn't allow the operation.

Constructing Server Sockets • Normally you only specify the port you want to listen on, like this: try { ServerSocket ss = new ServerSocket(80); } catch (IOException e) { System.err.println(e); }

• When a ServerSocket object is created, it attempts to bind to the port on the local host given by the port argument. • If another server socket is already listening to the port, then a java.net.BindException, a subclass of IOException, is thrown. • No more than one process or thread can listen to a particular port at a time. This includes non-Java processes or threads. • For example, if there's already an HTTP server running on port 80, you won't be able to bind to port 80.

• On Unix systems (but not Windows or the Mac) your program must be running as root to bind to a port between 1 and 1023. • 0 is a special port number. It tells Java to pick an available port. • The getLocalPort() method tells you what port the server socket is listening on. This is useful if the client and the server have already established a separate channel of communication over which the chosen port number can be communicated. • FTP

A Simple Server // SimpleServer.java: a simple server program import java.net.*; import java.io.*; public class SimpleServer { public static void main(String args[]) throws IOException { // Register service on port 1234 ServerSocket s = new ServerSocket(1234); Socket s1=s.accept(); // Wait and accept a connection // Get a communication stream associated with the socket OutputStream s1out = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream (s1out); // Send a string! dos.writeUTF("Hi there"); // Close the connection, but not the server socket dos.close(); s1out.close(); s1.close(); } }

A Simple Client // SimpleClient.java: a simple client program import java.net.*; import java.io.*; public class SimpleClient { public static void main(String args[]) throws IOException { // Open your connection to a server, at port 1234 Socket s1 = new Socket("mundroo.cs.mu.oz.au",1234); // Get an input file handle from the socket and read the input InputStream s1In = s1.getInputStream(); DataInputStream dis = new DataInputStream(s1In); String st = new String (dis.readUTF()); System.out.println(st); // When done, just close the connection and exit dis.close(); s1In.close(); s1.close(); } }

Expanding the Queue • If you think you aren't going to be processing connections very quickly you may wish to expand the queue when you construct the server socket. For example, • • • • • •

try { ServerSocket httpd = new ServerSocket(80, 50); } catch (IOException e) { System.err.println(e); }

Finding a free port import java.io.*; import java.net.*; class findAPort { public static void main (String[] args) { for (int i = 1024; i < 65535; i++) { try { ServerSocket freePort = new ServerSocket(i); System.out.println("The first free port is: " + i); freePort.close(); // always a good practice to close when finished System.exit(i); // to exit the loop and program; i is arbitrary } catch(IOException ioe) { // control falls into this block if there is a server on port i } } // end for } // end main } // end findAPort

Server in loop // SimpleServerLoop.java: a simple server program that runs forever in a single thead import java.net.*; import java.io.*; public class SimpleServerLoop { public static void main(String args[]) throws IOException { // Register service on port 1234 ServerSocket s = new ServerSocket(1234); while(true) { Socket s1=s.accept(); // Wait and accept a connection // Get a communication stream associated with the socket OutputStream s1out = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream (s1out); // Send a string! dos.writeUTF("Hi there"); // Close the connection, but not the server socket dos.close(); s1out.close(); s1.close(); } } }

import java.io.*; import java.net.*; class viewPorts { public static void main (String[] args) { Socket socketIn; String host = "localhost"; If (args.length > 0) { host = args[0]; } for (int i = 0; i < 1024; i++) { try {socketIn = new Socket(host, i); // to open a socket System.out.println("Port " + i + " hosts TCP service"); socketIn.close(); // to close the open socket } catch(UnknownHostException uhe) { System.err.println(uhe); break; } catch(IOException ioe) { // System.out.println("Port " + i + " does not host TCP service"); // output statement is commented out to avoid a lengthy output } } // end for } // end main } // end viewPorts

To find a TCP port

import java.io.*; import java.net.*; class smtp { public static void main (String[] args) { String host = "localhost"; // default is local host String mesg = "mail from: [email protected]" + "\n" + "rcpt to: [email protected]\n" + try { Socket socketIO = new Socket(host, 25); // 25 is smtp server "data\n" + "This is a test\n" DataInputStream socketIn = + ".\n" + "quit\n"; new DataInputStream(socketIO.getInputStream()); if (args.length > 0) DataOutputStream socketOut = { host = args[0]; } new DataOutputStream(socketIO.getOutputStream());

Access SMTP from Socket

socketOut.writeBytes(mesg); // write to socket while (true) { System.out.write(socketIn.readByte()); } } // end try catch(UnknownHostException uhe) { System.err.println(uhe); } catch(IOException ioe) { //System.out.println(ioe); } finally { System.out.println(); //socketIO.close(); //not defined he } // end main } // end smtp

The UDP Classes • Java's support for UDP is contained in two classes: java.net.DatagramSocket java.net.DatagramPacket

• A datagram socket is used to send and receive datagram packets.

java.net.DatagramPacket • a wrapper for an array of bytes from which data will be sent or into which data will be received. • also contains the address and port to which the packet will be sent.

java.net.DatagramSocket • A DatagramSocket object is a local connection to a port that does the sending and receiving. • There is no distinction between a UDP socket and a UDP server socket. • Also unlike TCP sockets, a DatagramSocket can send to multiple, different addresses. • The address to which data goes is stored in the packet, not in the socket.

UDP ports • Separate from TCP ports. • Each computer has 65,536 UDP ports as well as its 65,536 TCP ports. • A server socket can be bound to TCP port 20 at the same time as a datagram socket is bound to UDP port 20.

Datagram socket constructors • DatagramSocket() − Constructs a datagram socket and binds it to any available port on the local host machine. • DatagramSocket(int port) − Constructs a datagram socket and binds it to the specified port on the local host machine. • DatagramSocket(int port, InetAddress laddr) − Creates a datagram socket, bound to the specified local address.

Datagram socket Methods close() getLocalAddress() getLocalPort() receive(DatagramPacket p) send(DatagramPacket p) setSoTimeout(int t) getSoTimeout()

Datagram Packet class This class represents a datagram packet. ° The DatagramPacket class assembles data bytes into packets called datagrams for delivery. ° It disassembles and extracts data contents from datagrams received from a remote site.

Two DatagramPacket Constructors DatagramPacket(byte[] buf, int length) − Constructs a DatagramPacket for receiving packets of length length. DatagramPacket(byte[] buf, int offset, int length) − Constructs a DatagramPacket for receiving packets of length length, specifying an offset into the buffer. DatagramPacket(byte[] buf, int length, InetAddress address, int port) − Constructs a datagram packet for sending packets of length length to the specified port number on the specified host. DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) − Constructs a datagram packet for sending packets of length length with offset offset to the specified port number on the specified host.

Datagram packet methods • • • • • • • •

getAddress() getData() getLength() getPort() setAddress() setData() setLength() setPort()

Java server UDP example import java.io.*; import java.net.*;

String sentence = new String(receivePacket.getData());

InetAddress IPAddress = receivePacket.getAddress(); class UDPServer { public static void main(String args[]) throws Exception int port = receivePacket.getPort(); { String capitalizedSentence = sentence.toUpperCase(); DatagramSocket serverSocket = new DatagramSocket(9876); sendData = capitalizedSentence.getBytes(); byte[] receiveData = new byte[1024]; byte[] sendData = new byte[1024]; DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); while(true) { serverSocket.send(sendPacket); DatagramPacket receivePacket =} } new DatagramPacket(receiveData, receiveData.length); } serverSocket.receive(receivePacket);

import java.io.*; import java.net.*; class UDPClient {

A UDP Client

public static void main(String args[]) throws Exception { = sentence.getBytes(); BufferedReader inFromUser sendData =

DatagramPacket sendPacket = new BufferedReader(new InputStreamReader(System.in)); new DatagramPacket(sendData, sendData.length, DatagramSocket clientSocket = new DatagramSocket(); IPAddress, 9876); InetAddress IPAddress = InetAddress.getByName("hostname"); clientSocket.send(sendPacket); byte[] sendData = new byte[1024]; DatagramPacket receivePacket = byte[] receiveData = new byte[1024]; new DatagramPacket(receiveData, receiveData.length); String sentence = inFromUser.readLine(); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); }}