Lecture note 6

Download Report

Transcript Lecture note 6

COMPS311F
Li Tak Sing
Connectionless transmission
 The advantages of using connection-oriented transmission:
 reliable. The data will be retransmissed if it is lost.
 the order of the data is presvered.
 Disadvantage:
 there is overhead in creating a connection between two point.
 Therefore, if reliability is not the prime concern, we can use
connectionless transmssion. For example, in transmiting
audio signal, a packet lost will only affect the audio playing
for a very short period of time.
Connectionless transmission
 Advantage
 efficient. There is no need to establish a connection first before
transmission.
 Disadvantages
 there may be data loss. The sender would not know the loss and
therefore would not be able to resend it.
 The order of the data arriving at the destination is not
garantteed to be the same as that when they are sent.
Datagram
 DatagramSocket is the one in Java used in connectionless
transmission.
 In connectionless transmission, there is no difference
between a server and a client. Both use the same socket for
reading and writing packets. The only difference is that the
server must specify a port for the socket, but there is no need
for the client to specify a port. The system will randomly
assign a port for the client. However, a client can still specify
a port if he/hse insists.
 DatagramPacket is used to carry the data between the sender
and receiver.
DatagramSocket
 Two commonly used constructors
 DatagramSocket(int port)
 This is mainly used in a server.
 DatagramSocket()
 This is mainly used in a client.
Methods of DatagramSocket
 public void send(DatagramPacket p) throws IOException
 This method is used to send a packet to somewhere. The
destination is specified in the DatagramPacket. Note that the
sender would not know that the packet has reached the
destination or not.
 public void receive(DatagramPacket p) throws IOException
 This method receives a packet from the socket. When the
method returns, the buffer in the DatagramPacket is filled with
data from the sender. The DatagramPacket would also contains
the IP address, port number of the source so that we can send
back a reply.
Methods of DatagramSocket
 public void close()
 closes this datagram socket.
Constructors of DatagramPacket
 public DatagramPacket(byte[] buf, int len)
 Constructs a DatagramPacket for receiving packets of length
len. len must be less than or equal to buf.length. Note that the
destination of the packet has not been specified. Usually, this is
used for receiving a packet.
 public DatagramPacket(byte[] buf, int off, int len,
InetAddress address, int port)
 Constructs a datagram packet for sending packets of length len
with offset off to the specified port at the address. Usually this is
for sending a packet.
Methods of DatagramPacket
 public InetAddress getAddress()
 Returns the IP address of the machine to which this datagram is
being sent or from which the datagram was received.
 public int getPort()
 Returns the port number on the remote host to which this
datagram is being sent or from which the datagram was
received.
 public byte[] getData()
 Returns the data buffer. The data received or the data to be sent
starts from the offset in the buffer, and runs for length long.
Methods of DatagramPacket
 public int getLength()
 Returns the length of the data to be sent or the length of the
data received.
 public int getOffset()
 Returns the offset of the data to be sent or the offset of the data
received.
 public void setAddress(InetAddress iaddr)
 Sets the IP address of the machine to which this datagram is
being sent.
 public void setPort(int iport)
 Sets the port number on the remote host to which this
datagram is being sent.
Methods of DatagramPacket
 public void setData(byte[] buf)
 Set the data buffer for this packet. With the offset of this
DatagramPacket set to 0, and the length set to the length of buf.
In the server
 In a server:
DatagramSocket socket=new DatagramSocket(12345);
while (true) {
byte b[]=new b[1000];
DatagramPacket p=new DatagramPacket(b,0,b.length);
socket.receive(p);
.... // do something about the client
DatagramPacket rp=new DatagramPacket(c, off, len,
p.getAddress(), p.getPort());
socket.send(rp);
....
}
To DatagramPacket
 Since DatagramPacket can only carry data in byte[], we need
to convert all data types into byte[] before they can be sent to
a DatagramPacket. This can be done by
ByteArrayOutputStream:
ByteArrayOutputStream out=new ByteArrayOutputStream();
DataOutputStream output=new DataOutputStream(out);
output.writeInt(3);
output.writeUTF("abc");
output.close();
byte[] b=out. toByteArray();
From DatagramPacket
 Similarly we need to use a ByteArrayInputStream to extract
the data from a byte[].
DatagramPacket p=new DatagramPacket(b,b.length);
socket.receive(p);
DataInputStream input=new DataInputStream(
new ByteArrayInputStream(p.getData(), p.getOffset(),
p.getLength());
int i=input.readInt();
String st=input.readUTF();
....
In the client
DatagramSocket socket=new DatagramSocket();
DatagramPacket p=new DatagramPacket(b,off,len, address,
12345);
socket.send(p);
...
DatagramPacket rp=new DatagramPacket(c,0,c.length);
socket.receive(rp);
A simple echo server
 The server would receive packets from any clients. The
packets contain a string from the clients. The server would
display the string on its window and return another packet
that contains the string.
The echo client
 The echo client allows the user to type in message and then it
would be sent to the server after pressing a button. The
server would send back the same message and it would be
displayed in the client's window.
EchoServer
 The echo server can be downloaded at:
http://plbpc001.ouhk.edu.hk/~mt311f/examples/mt3112010
/src/datagram.tgz
 It is a JFrame which contains a textarea called text for the
display of messages from clients. The main login of the
program is an infinite loop that containuously read from the
DatagramSocket.
java.net.DatagramSocket ss = new java.net.DatagramSocket(12345);
byte[] buf = new byte[2000];
while (true) {
java.net.DatagramPacket p = new java.net.DatagramPacket(buf, buf.length);
ss.receive(p);
java.io.DataInputStream input = new java.io.DataInputStream(
new java.io.ByteArrayInputStream(p.getData(), p.getOffset(), p.getLength()));
java.net.InetAddress address = p.getAddress();
int port = p.getPort();
String st = input.readUTF();
input.close();
text.append(address + ":" + port + ":" + st + "\n");
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
java.io.DataOutputStream output = new java.io.DataOutputStream(out);
output.writeUTF("echo:" + st);
output.close();
byte rb[] = out.toByteArray();
java.net.DatagramPacket rp = new java.net.DatagramPacket(rb, 0, rb.length, address,
port);
ss.send(rp);
The client
public void actionPerformed(ActionEvent e) {
try {
java.io.ByteArrayOutputStream out = new
java.io.ByteArrayOutputStream();
java.io.DataOutputStream output = new
java.io.DataOutputStream(out);
output.writeUTF(textfield.getText());
textfield.setText("");
output.close();
byte[] b = out.toByteArray();
java.net.DatagramPacket p = new java.net.DatagramPacket(b, 0,
b.length, home, 12345);
socket.send(p);
byte[] b2 = new byte[2000];
java.net.DatagramPacket rp =
newjava.net.DatagramPacket(b2, b2.length);
socket.receive(rp);
java.io.DataInputStream input = new
java.io.DataInputStream(new
java.io.ByteArrayInputStream(rp.getData(), rp.getOffset(),
rp.getLength()));
String st = input.readUTF();
text.append(rp.getAddress() + ":" + rp.getPort()
+ ":" + st + "\n");
} catch (Exception ee) {
ee.printStackTrace();
}
}
A Multithreaded server
 The echo server we just showed is a single threaded server.
This means that it can only serve one client at a time. If a
packet comes when the server is busy serving another
packet, then the former one will be dropped. The sender of
this packet would not know that the packet has been
dropped.
 To make a more reliable server, we can use a multithreaded
server.
A Multithreaded server
 In a server:
DatagramSocket socket=new DatagramSocket(12345);
while (true) {
byte b[]=new b[1000];
DatagramPacket p=new DatagramPacket(b,0,b.length);
socket.receive(p);
new MyThread(p).start(); //MyThread is a thread which
//will handle the packet.
}
MultithreadedEchoServer
 An inner class MyThread is defined in the server.
private class MyThread extends Thread {
private java.net.DatagramPacket packet;
public MyThread(java.net.DatagramPacket packet) {
this.packet = packet;
}
public void run() {
try {
java.io.DataInputStream input = new java.io.DataInputStream(new
java.io.ByteArrayInputStream(packet.getData(), packet.getOffset(),
packet.getLength()));
java.net.InetAddress address = packet.getAddress();
int port = packet.getPort();
String st = input.readUTF();
input.close();
text.append(address + ":" + port + ":" + st + "\n");
java.io.ByteArrayOutputStream out = new
java.io.ByteArrayOutputStream();
java.io.DataOutputStream output = new
java.io.DataOutputStream(out);
output.writeUTF("echo:" + st);
output.close();
byte[] rb = out.toByteArray();
java.net.DatagramPacket rp = new java.net.DatagramPacket(rb,
0, rb.length, address, port);
ss.send(rp);
} catch (IOException ex) {
Logger.getLogger(MultithreadedEchoServer.class.getName()).log(Level.SE
VERE, null, ex);
}
}
}
Remote Method Invocation(RMI)
 For distributed computing.
 A Java object on one system can invoke a method in an object
on another system on the network.
 It is build on top of sockets. Users there do not have to
handle the sockets anymore. Communication between
different computers can be done by invoking methods on a
remote computers.
How Does RMI work?
 Normal objects are called local objects.
 Objects that can be accessibled by RMI are called remote
objects.
 For an object to be accessible remotely, there must be an
interface defined in both server and client. The client would
only use the interface to access the methods.
 The interface must be extended from java.rmi.Remote.
Key components of RMI
■ Server object interface: A subinterface of
java.rmi.Remote that defines the methods for the server
object.
■ Server class: A class that implements the remote object
interface.
■ Server object: An instance of the server class.
■ RMI registry: A utility that registers remote objects and
provides naming services for locating objects.
Key components of RMI
■ Client program: A program that invokes the methods in
the remote server object.
■ Server stub: An object that resides on the client host and
serves as a surrogate for the remote server object.
■ Server skeleton: An object that resides on the server host
and communicates with the stub and the actual server object.
Operations of RMI
Operations of RMI
1. A server object is registered with the RMI registry.
2. A client looks through the RMI registry for the remote
object.
3. Once the remote object is located, its stub is returned in the
client.
4. The remote object can be used in the same way as a local
object. Communication between the client and the server is
handled through the stub and the skeleton.
Passing Parameters
■ Primitive data types, such as char, int, double, or boolean,
are passed by value like a local call.
■ Local object types, such as java.lang.String, are also passed by
value, but this is completely different from passing an object
parameter in a local call. In a local call, an object parameter’s
reference is passed, which corresponds to the memory
address of the object. In a remote call, there is no way to pass
the object reference, because the address on one machine is
meaningless to a different JVM. Any object can be used as a
parameter in a remote call as long as it is serializable. The
stub serializes the object parameter and sends it in a stream
across the network. The skeleton deserializes the stream into
an object.
Passing Parameters
■ Remote object types are passed differently from local
objects. When a client invokes a remote method with a
parameter of a remote object type, the stub of the remote
object is passed. The server receives the stub and manipulates
the parameter through it.
RMI Registry
 java.rmi.registry.LocateRegistry has the following static
methods:
 public Registry getRegistry(): get the local registry at default
port of 1099.
 public Registry getRegistry(int port): get the local registry at
the specified port.
 public getRegistry(String host): get the remote registry at
default port of 1099 on a remote computer.
 public getRegistry(String host, int port): get the remote
registry at the specified port on a remote computer.
Methods of
java.rmi.registry.Registry
 void rebind(String name, Remote obj): bind the specified
name to the remote object.
 void unbind(String name): unbind the name.
 Remote lookup(String name): return a reference of a remote
object in the registry.
Developing RMI Applications
1. Define a server object interface that serves as the contract
between the server and its clients, as shown in the following
outline:
public interface ServerInterface extends Remote{
public void service1(...) throws RemoteException;
// Other methods
}
A server object interface must extend the java.rmi.Remote
interface.
Developing RMI Applications
2. Define a class that implements the server object interface, as shown
in the following outline:
public class ServerInterfaceImpl extends UnicastRemoteObject
implements ServerInterface {
public void service1(...) throws RemoteException {
// Implement it
}
// Implement other methods
}
Developing RMI Applications
3. Create a server object from the server implementation class and
register it with an RMI registry:
ServerInterface server = new ServerInterfaceImpl(...);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("RemoteObjectName", obj);
Before running this program, start the RMI registry by running
the command rmiregistry at a location where you can find
the classes for the server. This can be done by setting
appropriate class path or run the command at a suitable
location.
Developing RMI Applications
4. Develop a client that locates a remote object and invokes its
methods, as shown in the following outline:
Registry registry = LocateRegistry.getRegistry(host);
ServerInterface server = (ServerInterfaceImpl)
registry.lookup("RemoteObjectName");
server.service1(...);
A simple RMI server that adds two
integers.
 You can download the code at:
http://plbpc001.ouhk.edu.hk/~mt311f/examples/mt311201
0/src/rmi.tgz
 The server has just one method:
 public int sum(int i,int j)
 The method would return the sum of i and j.
RMIAddServer
public interface RMIAddServer extends Remote {
public int sum(int i, int j) throws RemoteException;
//this method will return the sum of the two integers.
}
RMIAddServerImp
public class RMIAddServerImp extends UnicastRemoteObject
implements RMIAddServer {
public RMIAddServerImp() throws RemoteException {
}
public int sum(int i, int j) throws RemoteException {
return i+j;
}
RMIAddServerImp
public static void main(String st[]) throws RemoteException {
RMIAddServerImp obj=new RMIAddServerImp();
Registry registry= LocateRegistry.getRegistry();
registry.rebind("add", obj);
}
}
ADDClient
public class AddClient {
public static void main(String st[]) throws RemoteException,
NotBoundException {
Registry registry=LocateRegistry.getRegistry("localhost");
RMIAddServer
server=(RMIAddServer)registry.lookup("add");
System.out.println("The sum of 3 and 4 is
"+server.sum(3, 4));
}
}
Start the server
 execute rmiregistry at a place where
RMIAddServerImp.class can be found. Note that if we have
use a package for RMIAddServerImp, then we should run
rmiregistry at the parent directory of the package.
RMI vs. Socket-Level Programming
 RMI enables you to program at a higher level of abstraction.
You do not need to open, close a socket.
 RMI server is already multithreaded. So you do not have to
worry about multithreading.