Java: Remote Method Invocation
The Java RMI (Remote Method Invocation) is a way to create distributed services. It is composed of RMIRegistry which is a name registry which saves the resources available (servers) in a JVM (Java Virtual Machine). The registry is, however, accessible through different JVM’s when configured.
Since all the invocations are remote, most arguments are passed by value. The exception is when an object the implements an interface that extends Remote. A server is passed by reference, since its concept (RemoteObject) requires that the information must to be consistent between all the clients accessing it.
Considering that the server object would be passed by value like any other argument. This means that for the server to be consistent between all clients, it would need for each client to relay the local changes of each individual server to the central server, this creates alot of useless workload since its easier to just change the central server directly, it would save CPU cycles and network traffic on the client side used to calculate the changes and the central server load doesn’t change.
Interface
public interface IStuffServer extends Remote
{
public void doStuff() throws RemoteException;
}
Class
public class StuffServer extends UnicodeRemoteObject implements IInfoReceiver
{
StuffServer() throws RemoteException { super(); }
public void doStuff() { System.out.println("Stuff done."); }
}
Every method of a class which extends Remote might throw a RemoteException (network connectivity).
Registering a resource
To create a registry there is a static method in the class LocateRegistry named createRegistry which receives an integer that specifies the port in which the registry will listen for requests. For the registry to be able to communicate with other JVM’s, it is needed to enable it by defining a policy.
policy.all
grant {
permission java.security.AllPermission "", "";
};
Please bear in mind this might be insecure for critical applications.
Creating a “public” registry
System.getProperties().put("java.security.policy", "policy.all");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try { // start rmiregistry
LocateRegistry.createRegistry(1099);
} catch (RemoteException e)
{ /* registry already created*/ }
InfoServerImpl server = new InfoServerImpl();
Naming.rebind("/StuffServer", server);
System.out.println("StuffServer bound in registry");
After creating the registry, the static class Naming is used to bind a name to the class using the method rebind, which in the example is “/StuffServer”. This name is only known by the registry in the current JVM.
A registry can be accessed by a simple netbios-like link, for example “//localhost/StuffServer”.
Obtaining Server Reference
To obtain the server object reference the static Naming class is used again, this time with the lookup method.
IInfoServer server = null;
try {
server = (IInfoServer) Naming.lookup("//localhost/StuffServer");
} catch(RemoteException e)
{ System.out.println("Server not found"); }
After the server reference is obtained all the interaction to it is the same of a local object, except it might fail/be slower because of network connectivity issues.
server.doStuff();
The previous will print “Stuff done.” at the server’s console.
That was it about Java’s RMI. For more information go here.
Thank you for reading!
Multicast: An UDP strong point
Multicast is a way to distribute UDP messages to multiple hosts in an automated fashion. It works by making every host join a group which is composed of an IP address in the range [224.0.0.0 - 239.255.255.255] and a port. Every message sent to a group will be delivered to every host that has joined it. Since it can generate alot of traffic, multicast is only used at a LAN or intranet level.
In Java, to use Multicast there is an object named MulticastSocket. It has mostly the same usage as the DatagramSocket but has an joinGroup method and makes the process join a multicast group:
MulticastSocket mso = new MulticastSocket( 9001 );
mso.joinGroup( InetAddress.getByName("224.0.5.8") );
For more information about receiving and sending messages in UDP go here.
HTTP Proxy: Java Implementation
Continuing from “Concept Introduction” we will now see how a possible implementation is done. To start implementing a proxy we must first create a simple server application which accepts a connection from a client to be redirected.
Creating Server
We start by creating a ServerSocket (for more information go here).
doIt( new ServerSocket( serverPort ) );
Now we need to implement the method doIt() which simply uses a non-stopping cycle to take requests.
public static void doIt( ServerSocket server )
{
for(;;)
{
try
{
Socket request = server.accept();
new RequestHandler( request ).start();
}
catch( IOException e )
{ e.printStackTrace(); continue; }
}
}
Creating a RequestHandler
The object RequestHandler is the one that actually does all the work for one request. Because of that we thread it (more information here) so that the proxy can handle multiple requests at once. The utility functions used here are located at the end of the post.
The code to convert the request to HTTP/1.0 is as follows:
InputStream srcIs = source.getInputStream();
String req = readLine(srcIs);
Scanner head = new Scanner(req);
String request = head.next();
String[] link = parseUrl(head.next());
if(link[0].compareTo("http") != 0)
throw new IOException("Incompatible Protocol");
request += String.format(" %s HTTP/1.0\r\n", link[3]);
String[] currentProperty = parseHttpHeader( readLine(srcIs) );
while(currentProperty != null)
{
if(isBanned(currentProperty))
{
currentProperty = parseHttpHeader( readLine(srcIs) );
continue;
}
request += String.format("%s:%s\r\n", currentProperty[0],
currentProperty[1]);
currentProperty = parseHttpHeader( readLine(srcIs) );
}
request += "\r\n"; // Add last CRLF
The function isBanned is the filter for properties from HTTP/1.1:
private boolean isBanned(String[] property)
{
return property[0].compareTo("Connection") == 0 ||
property[0].compareTo("Keep-Alive") == 0 ||
property[0].compareTo("Proxy-Connection") == 0;
}
Now that the request is ready, the only thing needed to be done, is to send the request and then dump the whole response from the server to the client.
InetAddress host = InetAddress.getByName(link[1]);
Socket destination = new Socket(host, Integer.parseInt(link[2]) );
OutputStream destOs = destination.getOutputStream();
InputStream destIs = destination.getInputStream();
destOs.write(request.getBytes());
dumpStream(destIs, source.getOutputStream());
destination.close();
source.close();
Note: source is a socket that is passed in the RequestHandler constructor.
Utility Functions
- The parseHttpHeader function parses the properties that a normal HTTP request has so we can easily remove the properties that are exclusive to HTTP1.1.
public static String[] parseHttpHeader( String header )
{
String[] result = new String[2];
int pos0 = header.indexOf( ':' );
if( pos0 == -1 )
return null;
result[0] = header.substring( 0, pos0 ).trim();
result[1] = header.substring( pos0 + 1 ).trim();
return result;
}
- The readLine function keeps reading from a InputStream until it reaches a “\r\n”.
public static String readLine( InputStream is ) throws IOException
{
StringBuffer sb = new StringBuffer();
int c;
while( (c = is.read() ) >= 0 ) {
if( c == '\r' ) continue;
if( c == '\n' ) break ;
sb.append( new Character( (char)c ) );
}
return sb.toString();
}
- The parseUrl function parses a header, for example “http://almightybuserror.com:5000/stuff/here/” will be transformed to: [“http”, “almightybuserror.com”, “5000”, “/stuff/here/”].
public static String[] parseUrl(String url)
{
String result[] = new String[4];
int i = url.indexOf(':');
result[0] = url.substring(0, i); // Protocol
result[1] = url.substring(i+3);
i = result[1].indexOf(':'); // Get possibly a port number
int j = result[1].indexOf('/');
// To parse the rest of the request
result[2] = (i > 0 ? result[1].substring(i+1, j) : "80");
result[3] = result[1].substring(j); // Request
result[1] = (i > 0 ? result[1].substring(0, i) :
result[1].substring(0, j));
//Concat so only the host remains
return result;
}
- The dumpStream function will also be used, you can find it here.
Thank you for reading. Comments are welcome!
Note: Credits for the functions readLine and parseHttpHeader go to ASC Department.
HTTP Proxy: Concept introduction
An HTTP proxy is a program that acts as a seamless server (since the user does not notice its existence under normal circumstances) and forwards HTTP (Hyper Text Transfer Protocol) traffic.
A problem for people that are creating a proxy for learning purposes is that most browsers nowadays days use HTTP/1.1 which is far more complex than its HTTP/1.0 counterpart implementation-wise. For this very reason we will convert every HTTP/1.1 requests to HTTP/1.0.
For a browser using HTTP/1.0 to fetch a webpage, it first needs to establish a connection with the webserver and use a “GET” command on the index (or another page if specified). When it finishes receiving and processing that page, the browser identifies every resource the page uses (be it images, scripts or Cascading Style Sheets). For each resource it needs, the browser creates a connection and sends a request. The webserver closes the connection after it finishes sending the resource.
The proxy will work like the following:

A browser using HTTP/1.1 does, however use pipelining and persistent connections, which after requesting and receiving the webpage the server does not close the connection, and can keeps receiving requests from the browser for resources avaiable locally until the client closes the connection (by using the Connection property with keep-alive value).
For the proxy to convert the request headers to HTTP/1.0 it is needed to read and modify them, removing some fields from the HTTP/1.1 request.
For our purposes we will remove “Connection” and the non-obligatory “Keep-Alive” and “Proxy-Connection” properties since they are unique to HTTP/1.1 and change the protocol version from the header. Every line of a HTTP request and response ends using two special characters “\r\n”.
Example:
GET http://almightybuserror.com/ HTTP/1.1
Connection: keep-alive
And this last request gets converted and sent to the server “almightybuserror.com” as:
GET / HTTP/1.0
Note: There needs to exist an extra “\r\n” at the end of the request since it is the only way the server involved knows that the request has ended.
Thank for reading. Comments are welcome.
The connection-oriented network protocol
The TCP (Transmission Control Protocol) and unlike UDP it does have a connection definition within the protocol based on Acknowledge-type packets.
In TCP every sent information packet needs to be acknowledged by the destination and if it is missing, the packet is resent until there is confirmation thus creating a “connection” between two peers. If a packet is corrupted a request is to the source for a replacement. Because there is a need to acknowledge all sent packets and error correction, TCP becomes bulkier and slower than UDP but extremely reliable.
In Java, to implement TCP communication the following objects from the java.net.* package are used: Socket and ServerSocket. Other needed objects, from the java.io.* package: InputStream and OutputStream.
As you can see in Java there is such a thing as a Server and Client. A ServerSocket can be looked at as a Socket generator. Its accept method accepts an incoming connection from a client creating and returning a Socket object.
How to use a Socket:
Socket aSocket = new Socket( server, port );
Reading from the socket:
InputStream is = aSocket.getInputStream();
Scanner in = new Scanner( is );
( ... )
For more information on how to use a Scanner please refer to here.
Writing to the socket:
OuputStream os = aSocket.getOutputStream();
byte[] message = new String( "Hello World!" ).getBytes();
os.write( message );
Closing a socket:
socket.close();
How to use a ServerSocket:
ServerSocket server = new ServerSocket( port );
Socket aSocket = server.accept();
The accept method is blocking, it will block the current execution flow. If there is need to process multiple clients at the same time the program must be multithreaded.
As we can observe, opposing UDP, the TCP approach, at least in Java, does not need a crafting of every single packet, there is an abstraction layer that makes it possible to just dump information and let the underlying implementation handle the low-level management.
For more information on TCP go here.
Thank you for reading!
The connectionless networking protocol
Also known as UDP (User Datagram Protocol), like the title suggests, it does not have a logical idea of connection.
The way it communicates is by datagrams (or messages). The protocol is not able assert any type of confirmation at a transport layer level if a message got thru to the destination. A collateral effect of this is that UDP is a very lightweight protocol, perfect for scenarios where the loss of some information does not break the intended application.
In Java, to implement UDP communication it’s mostly used the following two objects from the java.net.* package: DatagramPacket and DatagramSocket.
The DatagramPacket is used to create a datagram that will be received or sent and configure destination/port in the latter:
DatagramPacket packet = new DatagramPacket(
someString.getBytes(), someString.length() );
To configure the destination of the datagram the following methods are used:
packet.setAddress( InetAddress.getByName( someServerName ) );
packet.setPort( port );
InetAddress.getByName is an static method that given a server name like “www.google.com” returns the IP address.
A DatagramPacket can be used to send any type of message that has been converted to an array of byte. There is, however, an UDP protocol 65,507 byte limit to the size of the array.
To extract the information from a received packet the following methods are used:
byte[] info = packet.getData();
int infoLength = packet.getLength();
A DatagramSocket is initialized using the constructor that receives a port which will be used for sending and receiving datagrams:
DatagramSocket socket = new DatagramSocket( port );
The methods used by this object are:
socket.send( DatagramPacket x );
socket.receive( DatagramPacket x );
The receive method is blocking, it will block the current execution flow until it has received a message. To receive a packet, it doesn’t make sense to configure a destination and a port, only a buffer to where the data will be stored like in the declaration of the packet object. Since all the complex ( i.e. Object ) argument passing is by reference, the received packet will overwrite all the information in x.
For more information on UDP go here.
Hope this has been useful.
Thank you for reading!