CS865 – Distributed Software Development |
The Socket API |
Based on:
·
M.L. Liu, Distributed Computing: Principles and
Applications, Addison-Wesley, 2004, ISBN-10: 0201796449
·
Java Sockets 101 – PDF
Also See:
·
http://java.sun.com/docs/books/tutorial/networking/sockets/index.html
Introduction
Socket
Definition:
Bruce Eckel (Thinking in Java):
The
socket is the software abstraction used to represent the "terminals" of
a connection between two machines.
For a
given connection, there's a socket on each machine, and you can imagine a
hypothetical "cable" running between the two machines with each end
of the "cable" plugged into a socket.
Of
course, the physical hardware and cabling between machines is completely
unknown.
The
whole point of the abstraction is that we don't have to know more than is
necessary.
•The
socket API is an Interprocessing Communication (IPC) programming interface
originally provided as part of the Berkeley UNIX operating system.
•De
facto standard for programming IPC - the basis of more sophisticated
IPC interface such as remote procedure call and remote method invocation.
The conceptual model of the socket API
The socket API
· A socket API provides a programming construct termed a socket.
· A process wishing to communicate with another process must create an instance, or instantiate, such a construct
·
The two processes then issues operations provided by the API to
send and receive data.
Connection-oriented & connectionless datagram socket
A
socket programming construct can make use of either the UDP or TCP protocol.
·
Sockets that use UDP for transport are known as datagram sockets
·
Sockets that use TCP are termed stream sockets.
·
TCP
sockets (implemented by the Java Socket class)
·
UDP
sockets (implemented by the Java DatagramSocket class)
o Datagram
sockets can support both connectionless and connection-oriented
communication at the application layer.
TCP and UDP play the same role, but do it differently
·
Both
receive transport protocol packets and pass along their contents to the
Presentation Layer.
·
TCP divides messages into packets (datagrams)
and reassembles them in the correct sequence at the receiving end.
o
It
also handles requesting retransmission of missing packets.
o
With
TCP, the upper-level layers have much less to worry about.
·
UDP doesn't
provide assembly and retransmission requesting features.
o
It
simply passes packets along.
o
The
upper layers have to make sure that the message is complete and assembled in
correct sequence.
The Java Datagram Socket API
In
Java, two classes are provided for the datagram socket API:
1.
the DatagramSocket class for the sockets.
2.
the DatagramPacket class for the datagram exchanged.
A process wishing to send or receive data using this API must instantiate a DatagramSocket object, or a socket in short.
Each socket is said to be bound to a UDP port of the
machine local to the process
To send a datagram to another
process, a process:
·
creates an object that represents the datagram itself.
·
This object can be created by
instantiating a DatagramPacket object which carries
1.
the payload data as a reference to a byte array, and
2.
the destination address (the host ID and port number to which the
receiver’s socket is bound.
·
issues a call to a send method in the DatagramSocket
object, specifying a reference to the DatagramPacket
object as an argument
Receiving
process - a
DatagramSocket object:
·
must be instantiated and bound to a local port
·
the port number must agree with that specified in the datagram
packet of the sender.
·
the receive process creates a datagramPacket object
which references a byte array and calls a receive method in its DatagramSocket
object, specifying as argument a reference to the DatagramPacket
object.
The
Data Structures in the sender and receiver programs
The program flow in the sender and receiver programs
Connectionless sockets
·
Possible for multiple processes to simultaneously send datagrams to
the same socket established by a receiving process
·
The order of the arrival of these messages will be unpredictable,
in accordance with the UDP protocol
Setting timeout
·
To avoid indefinite blocking, a timeout can be set with a socket
object:
void setSoTimeout(int timeout)
·
Set a timeout for the blocking receive from this socket, in
milliseconds.
Once set, the timeout will be in effect for all blocking operations.
Key Methods and Constructors
The coding
Event synchronization with the connectionlss datagram socketsAPI
Example 1: One-way communication between two process
Example1Sender.java
import java.net.*; import java.io.*; /** * This example illustrates the basic method
calls for connectionless * datagram socket. * @author M. L. Liu */ public class Example1Sender { // An application which sends a
message using connectionless // datagram socket. // Three command line arguments
are expected, in order: // <domain name or IP address of the
receiver> // <port number of the receiver's
socket> // <message, a string, to send> public static void
main(String[] args) { if (args.length != 3) System.out.println ("This program requires
three command line arguments"); else { try { InetAddress receiverHost = InetAddress.getByName(args[0]); int receiverPort =
Integer.parseInt(args[1]); String message = args[2]; // instantiates a datagram socket
for sending the data DatagramSocket mySocket = new DatagramSocket(); byte[ ] buffer =
message.getBytes( ); DatagramPacket datagram = new DatagramPacket(buffer, buffer.length,
receiverHost, receiverPort); mySocket.send(datagram); mySocket.close( ); } // end try catch (Exception ex) { ex.printStackTrace( ); } } // end else } // end main } // end class |
Example1Receiver.java
import java.net.*; import java.io.*; /** * This example illustrates the basic method
calls for connectionless * datagram socket. * @author M. L. Liu */ public class Example1Receiver
{ // An application which receives
a message using connectionless // datagram socket. // A command line argument is
expected, in order: // <port number of the receiver's
socket> // Note: the same port number
should be specified in the // command-line arguments for the
sender. public static void main(String[] args) { if (args.length != 1) System.out.println ("This program requires a
command line argument."); else { int port = Integer.parseInt(args[0]); final int MAX_LEN = 10; // This is the assumed maximum
byte length of the // datagram to be received. try { DatagramSocket mySocket = new DatagramSocket(port); // instantiates a datagram
socket for receiving the data byte[ ] buffer = new
byte[MAX_LEN]; DatagramPacket datagram = new DatagramPacket(buffer, MAX_LEN); mySocket.receive(datagram); String message = new
String(buffer); System.out.println(message); mySocket.close( ); } // end try catch (Exception ex) { ex.printStackTrace( ); } } // end else } // end main } // end class |
Example 2: Two-way communication between two process
·
Example1Sender must
bind its socket to a specific address so Example1Receiver can
send data datagrams to that address.
·
MyDatagramSocket.java
is created as a
subclass of DatagramSocket with two instances for sending and
receiving messages.
·
Example2SenderReceiver program instantiates
a MyDatagramSocket object then calls its sendMessage method followed by a call to receiveMessage.
·
Example2ReceiverSender
instantiates a MyDatagramSocket object then calls its receiveMessage method followed by a call to sendMessage.
MyDatagramSocket.java
import java.net.*; import java.io.*; /** * A subclass of DatagramSocket which
contains * methods for sending and receiving messages * @author M. L. Liu */ public class MyDatagramSocket extends DatagramSocket { static final int MAX_LEN = 100; MyDatagramSocket(int
portNo) throws SocketException{ super(portNo); } public void sendMessage(InetAddress
receiverHost, int receiverPort, String message)
throws IOException { byte[ ] sendBuffer =
message.getBytes( ); DatagramPacket datagram = new DatagramPacket(sendBuffer, sendBuffer.length, receiverHost,
receiverPort); this.send(datagram); } // end sendMessage public String receiveMessage() throws IOException
{ byte[ ] receiveBuffer = new
byte[MAX_LEN]; DatagramPacket datagram = new DatagramPacket(receiveBuffer,
MAX_LEN); this.receive(datagram); String message = new
String(receiveBuffer); return message; } //end receiveMessage } //end class |
Example2SenderReceiver.java
import java.net.*; /** * This example illustrates a process which
sends then receives * using a datagram socket. * @author M. L. Liu */ public class Example2SenderReceiver { // An application which sends
then receives a message using // connectionless datagram
socket. // Four command line arguments
are expected, in order: // <domain name or IP address of the
receiver> // <port number of the receiver's
datagram socket> // <port number of this process's
datagram socket> // <message, a string, to send> public static void main(String[] args) { if (args.length != 4) System.out.println ("This program requires four
command line arguments"); else { try { InetAddress receiverHost = InetAddress.getByName(args[0]); int receiverPort =
Integer.parseInt(args[1]); int myPort = Integer.parseInt(args[2]); String message = args[3]; MyDatagramSocket mySocket = new MyDatagramSocket(myPort); // instantiates a datagram
socket for both sending // and receiving data mySocket.sendMessage(
receiverHost, receiverPort, message); // now wait to receive a datagram from the
socket
System.out.println(mySocket.receiveMessage()); mySocket.close( ); } // end try catch (Exception
ex) { ex.printStackTrace( ); } //end catch } //end else } //end main } //end class |
Example2ReceiverSender.java
import java.net.*; /** * This example illustrates a process which
sends then receives * using a datagram socket. * @author M. L. Liu */ public class Example2ReceiverSender { // An application which sends
then receives a message using // connectionless datagram
socket. // Four command line
arguments are expected, in order: // <domain name or IP address of the
receiver> // <port number of the receiver's
datagram socket> // <port number of this process's
datagram socket> // <message, a string, to send> public static void main(String[] args) { if (args.length != 4) System.out.println ("This program requires four
command line arguments"); else { try { InetAddress receiverHost = InetAddress.getByName(args[0]); int receiverPort =
Integer.parseInt(args[1]); int myPort = Integer.parseInt(args[2]); String message = args[3]; MyDatagramSocket mySocket = new
MyDatagramSocket(myPort); // instantiates a datagram
socket for both sending // and receiving data // First wait to receive a datagram from the
socket System.out.println(mySocket.receiveMessage()); // Now send a
message to the other process. mySocket.sendMessage(
receiverHost, receiverPort, message); mySocket.close( ); } // end try catch (Exception
ex) { ex.printStackTrace( ); } //end catch } //end else } //end main } //end class |
The Stream-mode Socket API
·
The datagram socket API supports the exchange of discrete
units of data (that is, datagrams).
·
The stream socket API provides a model of data transfer based
on the stream-mode I/O of the Unix operating systems.
·
By definition, a stream-mode socket supports connection-oriented
communication only.
Stream-mode Socket API (connection-oriented socket API)
Stream-mode Socket API
·
A stream-mode socket is established for data exchange between two
specific processes.
·
Data stream is written to the socket at one end, and read from the
other end.
·
A stream socket cannot be used to communicate with more than one
process.
Java
stream-mode
socket API is provided with two classes:
·
Server socket: for accepting connections; we will call an object of this class
a connection socket.
Socket: for data exchange; we will call an object of this class a data socket.
The server (the connection listener)
Key methods in the ServerSocket class
Note:
Accept is a blocking operation.
Key methods in the Socket class
A read operation on the InputStream is blocking.
A write operation is nonblocking.
Stream-mode Socket API program flow
Example: Stream Mode Sockets
MyStreamSocket.java
import java.net.*; import java.io.*; /** * A wrapper class of Socket
which contains * methods for sending and
receiving messages * @author M. L. Liu */ public class MyStreamSocket extends Socket { private Socket socket; private BufferedReader
input; private PrintWriter
output; MyStreamSocket(String
acceptorHost, int
acceptorPort ) throws SocketException,
IOException{ socket = new Socket(acceptorHost,
acceptorPort ); setStreams( ); } MyStreamSocket(Socket socket) throws IOException { this.socket =
socket; setStreams( ); } private void setStreams( ) throws IOException{ // get an input stream
for reading from the data socket InputStream inStream
= socket.getInputStream(); input = new
BufferedReader(new InputStreamReader(inStream)); OutputStream
outStream = socket.getOutputStream(); // create a
PrinterWriter object for character-mode output output = new
PrintWriter(new OutputStreamWriter(outStream)); } public void sendMessage(String
message) throws
IOException {
output.println(message); //The ensuing flush
method call is necessary for the data to // be written to the
socket data stream before the // socket is closed. output.flush(); } // end sendMessage public String receiveMessage( ) throws
IOException { // read a line from
the data stream String message =
input.readLine( ); return message; } //end receiveMessage public void close( ) throws
IOException { socket.close( ); } } //end class |
Example5ConnectionAcceptor.java
import java.net.*; import java.io.*; /** * This example illustrates
the basic syntax for stream-mode * socket. * @author M. L. Liu */ public class Example5ConnectionAcceptor { // An application which receives a message using stream-mode
socket // Two command line arguments are expected, in order: // <port number for
the the Server socket used in this process> // <message, a string,
to
send> public static void main(String[] args) { if (args.length !=
2)
System.out.println ("This program requires three
command line arguments"); else { try { int portNo =
Integer.parseInt(args[0]); String message
= args[1]; //
instantiates a socket for accepting connection ServerSocket connectionSocket =
new ServerSocket(portNo); /**/
System.out.println("now ready accept a connection"); // wait to
accept a connecion request, at which // time a data socket is created MyStreamSocket dataSocket = new
MyStreamSocket(connectionSocket.accept()); /**/
System.out.println("connection accepted");
dataSocket.sendMessage(message); /**/
System.out.println("message sent"); dataSocket.close( ); /**/
System.out.println("data socket closed");
connectionSocket.close( ); /**/
System.out.println("connection socket closed"); } // end try catch (Exception ex) { ex.printStackTrace(
); } // end catch } // end else } // end main } // end class |
Example5ConnectionRequestor.java
import java.net.*; import java.io.*; /** * This example illustrates
the basic syntax for stream-mode * socket. * @author M. L. Liu */ public class Example5ConnectionRequestor { // An application that sends a message using stream-mode socket. // Two command line arguments are expected: // // <host name of the
connection accceptor> // <port number of the
connection accceptor> public static void
main(String[] args) { if (args.length !=
2)
System.out.println ("This
program requires two command line arguments"); else { try { String
acceptorHost = args[0]; int acceptorPort
= Integer.parseInt(args[1]); //
instantiates a data socket MyStreamSocket
mySocket = new
MyStreamSocket(acceptorHost, acceptorPort); /**/
System.out.println("Connection request granted"); String message
= mySocket.receiveMessage( ); /**/
System.out.println("Message received:");
System.out.println("\t" + message);
mySocket.close( ); /**/
System.out.println("data socket closed"); } // end try catch (Exception ex) {
ex.printStackTrace( ); } } // end else } // end main } // end class |
Event Diagram for Stream Mode Sockets
Secure Sockets
http://java.sun.com/products/jsse/
·
Secure sockets perform encryption on the
data transmitted.
·
The JavaTM Secure Socket
Extension (JSSE) is a Java package that enables secure Internet communications.
·
It implements a Java version of SSL (Secure
Sockets Layer) and TLS (Transport Layer Security) protocols
·
It includes functionalities for data
encryption, server authentication, message integrity, and optional client
authentication.
·
Using JSSE, developers can provide for
the secure passage of data between a client and a server running any
application protocol.
The
Java Secure Socket Extension API
http://java.sun.com/products/jsse/doc/apidoc/index.html
Import javax.net.ssl;
·
Class SSLServerSocket is a subclass of
ServerSocket, and inherits all its methods.
·
Class SSLSocket is a subclass of Socket,
and inherits all its methods.
·
There are also classes for
–Certification
–Handshaking
–KeyManager
–SSLsession