Saturday, October 23, 2010

Java Sockets

I had the fortunate experience of getting cross-over benefit at work from my unrelated home experiments in Linux (Ubuntu Experiment, 8/1/2010). A few weeks ago I had gone through Chapter 13 of GNU/Linux Application Programming, covering BSD4.4 Sockets API. I had gone through the sample code for the Daytime protocol server/client sockets in C and made my own socket server examples.

At work there was a customer issue related to a workflow engine that appeared to hang on sending emails through the client's SMTP servers. We had some basic questions on whether or not the workflow engine would hang or eventually timeout if it stayed connected to the server? Or cause exceptions?

It dawned on me I could easily set up a socket server that listened on the STMP port and simulated a server not releasing a connection just for a test.

The socket model is basically: Create Socket > Bind to an address > Listen > Accept client connection > [Data Transfer] > Close > loop back to Accept.

Given my recent experience it would be pretty trivial to replace [Data Transfer] with [Delay indefinitely] in order to see what effect that had. Since we use Windows 7 at work, and I didn't have the C code handy, I figured I would just write the same sort of socket server in Java.

I created a new class, SMTPServerSocket

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import javax.net.ServerSocketFactory;

Just a few necessary imports from java.net and javax.net packages.


public class SMTPSocketServer
{
public SMTPSocketServer(){
super();
}

Definition and default constructor


public static void main(String[] args)
{

try
{

//get the default server socket factory
ServerSocketFactory socketFactory = ServerSocketFactory.getDefault();

//port 25 - SMTP, allow a backlog of 1000 before connections are refused.
ServerSocket smtpServer = socketFactory.createServerSocket(25, 1000);

System.out.println("Started: "+smtpServer.getLocalSocketAddress().toString());
//TODO need a way to break out of this infinite loop
boolean listen = true;
while(listen){
System.out.println("Waiting for connection "+(new Date()));
Socket sock = smtpServer.accept();
//print some info on the connection
System.out.println("Accepted: "+sock.getInetAddress().toString());
System.out.println("SO_TIMEOUT: "+sock.getSoTimeout());
System.out.println("Data: "+sock.getReceiveBufferSize());

System.out.println("Sleeping "+(new Date()));
//sleep for n * 1000 milliseconds
Thread.sleep(2000 * 1000 );
System.out.println("Done "+(new Date()));
sock.close();
}
//close
smtpServer.close();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}

This was the main body. The socket is created using the ServerSocketFactory. I set it up to listen on port 25 (default SMTP port). I entered an infinite while loop. For the purposes of this demo I didn't build anything in that would allow it to break out of the loop. Ctrl+C seems to do the trick. The socket calls accept() which blocks until a client connects. Then when the client connects I printed some debug info, then put the process to sleep for a long amount of time to test the effects on our workflow engine. After the sleep period the connection is closed.

This actually ended up working ok. We proved that the workflow doesn't appear to have any timeout when it tries to connect to the SMTP server. I could reproduce the behavior of the hanging process while it waited on my SMTPServerSocket during the long sleep.

No comments:

Post a Comment