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();         }     } }

Friday, May 10, 2013

How to add log files using log4net


log4net is an open source library which is developed under Apache License. If you are developing an .NET web application and if you want to keep a log file, og4net is the best way to do so. You can simply follow following steps.
1. First you have to download Log4Net. You can download it from here.
2. Open the visual studio create a new .net web application or open an existing one.
3. Add log4net.dll to reference in your web application. You can find dll file from ~\log4net-1.2.11\bin\net\4.0\release\log4net.dll in the extracted folder.
4. Edit the web.config file in order to configure log4net by putting this code.
<configuration>
<configSections>
<section name=”log4net” type=”log4net.Config.Log4NetConfigurationSectionHandler,Log4net”/>
</configSections>
5. Add an xml file to do some configurations regarding log4net. (Including the maximum size of the log file, rolling style etc). The code is shown below.Save it as log4net.xml
<?xml version=”1.0″ encoding=”utf-8″ ?>
<log4net> <root> <level value=”DEBUG” /> <appender-ref ref=”LogFileAppender” /> </root> <appender name=”LogFileAppender” type=”log4net.Appender.RollingFileAppender” > <param name=”File” value=”.\Logs\log.txt” /> <param name=”AppendToFile” value=”true” /> <rollingStyle value=”Size” /> <maxSizeRollBackups value=”10″ /> <maximumFileSize value=”10MB” /> <staticLogFileName value=”true” /> <layout type=”log4net.Layout.PatternLayout”> <param name=”ConversionPattern” value=”%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n” /> </layout> </appender> </log4net>
6. Then add the following code into Global.asax, to configure log4net.xml file within the Application_Start() method.
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(Server.MapPath(“log4net.xml”)));
7. After that you can update log files by enabling which actions should be written. It can be any action in the code. For an example you can add following code to the Index action in Default controller.
public class DefaultController : BaseController
{ protected static readonly ILog log = LogManager.GetLogger(“root”); // // GET: /Default1/ public ActionResult Index(string fmt) { log4net.Config.XmlConfigurator.Configure(); log.Debug(“Action:- ” + this.ControllerContext.Controller.ToString() + “”); return GetFormatView(“Home/Home.aspx”); } }