Tuesday, May 14, 2013

Simultaneous read and write in Custom TCPMon

TCP Monitors are used to monitor messages passed through a TCP based communication. Apache TCPMon is one of the open source TCP Montor which is developed under Apache Software Licence. You can download TCPMon from here.

But when I used TCPMon to listen two way TCP communication by configuring the listen port and the  target port, I observed there is no simultaneous reading and writing for the two paths (from source to target and target to source).

Therefore a simple custom TCPMon is written to facilitate simultaneous read and write. Here is the approach I followed.

To listen from a port we can create a new Socket connection, configure the port and accept data. Here I have taken the listening port as 2389.

public static void main(String[] args) throws Exception {
        ServerSocket srcSocket = new ServerSocket(2389);
        while (true) {
            new Thread(new TCPServer(srcSocket.accept())).start();
        }
    }

It requires what is the target port that data should be sent to. Here the target port is 3456.

Socket targetSock = new Socket("localhost", 3456);

Then we can have input stream and the output stream from both socket connections.

        srcIn = srcSocket.getInputStream();
        srcOut = srcSocket.getOutputStream();
        targetIn = targetSock.getInputStream();
        targetOut = targetSock.getOutputStream();

Then we should pipe data from the input stream to output stream to have no data loss during communication.

private class Pipe extends Thread {

        private InputStream in;

        private OutputStream out;

        public Pipe(InputStream in, OutputStream out) {
            this.in = in;
            this.out = out;
        }

        public void run() {
            try {
                byte[] buff = new byte[512];
                int i;
                while (true) {
                    i = in.read(buff);
                    if (i > 0) {
                        out.write(buff, 0, i);
                        System.out.print(".");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
In order to have simultaneous data writing and reading operations two threads should be started.

        new Pipe(srcIn, targetOut).start();
        new Pipe(targetIn, srcOut).start();

Now our TCPMon works fine with simultaneous data passing.

The full code is shown below.
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer implements Runnable {

    private InputStream srcIn, targetIn;

    private OutputStream srcOut, targetOut;

    public TCPServer(Socket srcSocket) throws Exception {
        Socket targetSock = new Socket("localhost", 3456);
        srcIn = srcSocket.getInputStream();
        srcOut = srcSocket.getOutputStream();
        targetIn = targetSock.getInputStream();
        targetOut = targetSock.getOutputStream();
    }

    public void run() {
        new Pipe(srcIn, targetOut).start();
        new Pipe(targetIn, srcOut).start();
    }

    private class Pipe extends Thread {

        private InputStream in;

        private OutputStream out;

        public Pipe(InputStream in, OutputStream out) {             this.in = in;             this.out = out;         }         public void run() {             try {                 byte[] buff = new byte[512];                 int i;                 while (true) {                     i = in.read(buff);                     if (i > 0) {                         out.write(buff, 0, i);                         System.out.print(".");                     }                 }             } catch (Exception e) {                 e.printStackTrace();             }         }     }     public static void main(String[] args) throws Exception {         ServerSocket srcSocket = new ServerSocket(2389);         while (true) {             new Thread(new TCPServer(srcSocket.accept())).start();         }     } }

No comments:

Post a Comment