Saturday, May 26, 2012

Chat Client using TCP Sockets

This is just a simple chat client to work with the Chat server discussed in earlier post. it is a winform application that contains two textboxes one for message input and other for historical broadcast messages.


 public partial class Form1 : Form
    {
        StringBuilder history;
        TcpClient client = new TcpClient();
        NetworkStream clientStream;

        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
        }

        void Form1_Load(object sender, EventArgs e)
        {
            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
            history = new StringBuilder();
            try
            {
                client.Connect(serverEndPoint);
                clientStream = client.GetStream();
                lblStatus.Text = "Connected to Server";
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
            catch { lblStatus.Text = "Unable to Connect to Server"; }
        }


        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //blocks until a client sends a message
                    bytesRead = clientStream.Read(message, 0, 4096);

                }
                catch
                {
                    //a socket error has occured
                    break;
                }

                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    break;
                }

                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                var msg = encoder.GetString(message, 0, bytesRead);
                System.Diagnostics.Debug.WriteLine(msg);
                if (string.IsNullOrWhiteSpace(msg))
                    SendMessage(msg);
                else
                {
                    history.AppendLine(msg);
                    tbHistory.SetPropertyThreadSafe(() => tbHistory.Text, history.ToString());
                }
            }

            tcpClient.Close();
        }


        private void btnBroadcast_Click(object sender, EventArgs e)
        {
            if (clientStream != null && client != null && client.Connected)
            {
                SendMessage(tbMessage.Text);
                tbMessage.Text = string.Empty;
            }
        }

        private void SendMessage(string msg)
        {
            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] buffer = encoder.GetBytes(msg);
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            if (clientStream != null && client != null && client.Connected)
            {
                clientStream.Close();
                client.Close();
            }
            Application.Exit();

        }
    }

Multi-Threaded TCP Socket Chat Server

A multi-threaded chat server using c# .net. It accepts connections from the client and manage data reception in separate threads virtually unlimited clients can connect to this server depending on the machine capacity. This is just a server that will broadcast messages from the client to all other clients. also have some events to show server status and client count change.

Detecting client disconnect in abnormal situations like wire cut, improper shutdown,power failure are not supported by framework, we will have to periodically check for the client whether they are connected or not.





public class Server

    {

        //thread safe dictionary to store list of tcp client connection that will be used to broadcast

        ConcurrentDictionary AllClients { get; set; }
       

        #region Events
        public delegate void ClientCount(int count);
        private event ClientCount _ClientCountUpdated;
        public event ClientCount ClientCountUpdated
        {
            add { _ClientCountUpdated += value; }
            remove { _ClientCountUpdated -= value; }
        }

        private void RaiseCount(int count)
        {
            if (_ClientCountUpdated != null)
            {
               
                _ClientCountUpdated(count);
            }
        }


        public delegate void ServerStatus(string status);
        private event ServerStatus _StatusChanged;
        public event ServerStatus StatusChanged
        {
            add { _StatusChanged += value; }
            remove { _StatusChanged -= value; }
        }

        private void RaiseStatusChanged(string status)
        {
            if (_StatusChanged != null)
            {
                _StatusChanged(status);
            }
        }
        #endregion

        #region Properties
        private TcpListener tcpListener;
        private Thread listenThread;
        private int _TotalClientCount;
        private int TotalClientCount
        {
            get
            {
                lock (this)
                {
                    return _TotalClientCount;
                }
            }
            set
            {
                lock (this)
                {
                    _TotalClientCount = value;
                    RaiseCount(_TotalClientCount);
                }
            }
        }
        #endregion

        public Server()
        {
            AllClients = new ConcurrentDictionary();
            MonitorDisconnectedClients();
           
        }

        // this will monitor abnormal network disconnections
        private void MonitorDisconnectedClients()
        {
            new Thread(() =>
            {

                while (true)
                {
                    //an empty broadcast message similar to ping
                    BroadcastMessage(" ");
               
                    var clientsToRemove = AllClients.Values.Where(r => r.LastUpdate < DateTime.Now.AddSeconds(-5)).ToArray();
                    MyTcpClient temp = null;
                    foreach (var client in clientsToRemove)
                    {
                        client.Tcp.Close();
                        AllClients.TryRemove(client.GetHashCode().ToString(), out temp);
                    }
                    RaiseCount(AllClients.Count);
                    Thread.Sleep(5000);
                }
            }).Start();
        }

      

        public void Start()
        {
            RaiseStatusChanged("Starting...");
            this.tcpListener = new TcpListener(IPAddress.Any, 3000);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
            RaiseStatusChanged("Listening...");
        }

        //start to listen to tcp connections
        private void ListenForClients()
        {
            this.tcpListener.Start();

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = this.tcpListener.AcceptTcpClient();
                var myClient = new MyTcpClient(client);
                //add client connection to to the thread safe dictionary
                AllClients.AddOrUpdate(myClient.GetHashCode().ToString(), myClient, (key, value) => { return value; });
                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(myClient);
                RaiseCount(AllClients.Count);
            }
        }

        //this will handle messages comming from the client in a seperate thread
        private void HandleClientComm(object client)
        {
            MyTcpClient tcpClient = (MyTcpClient)client;
            NetworkStream clientStream = tcpClient.Tcp.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //blocks until a client sends a message
                    bytesRead = clientStream.Read(message, 0, 4096);
                   
                }
                catch
                {
                    //a socket error has occured
                    break;
                }

                if (bytesRead == 0)
                {
                   
                    AllClients.TryRemove(tcpClient.GetHashCode().ToString(), out tcpClient);
                    RaiseCount(AllClients.Count);
                    //the client has disconnected from the server
                    break;
                }

                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                var msg = encoder.GetString(message, 0, bytesRead);
                System.Diagnostics.Debug.WriteLine(msg);
                tcpClient.LastUpdate = DateTime.Now;
                if(!string.IsNullOrWhiteSpace(msg))
                    BroadcastMessage(msg);
            }

            tcpClient.Tcp.Close();
        }

        // this is used to broadcast messages to all other clients, also in another thread
        private void BroadcastMessage(string msg)
        {
            new Thread(() => {
                foreach (var item in AllClients)
                {
                    var tcpClient = item.Value;
                    if (tcpClient.Tcp.Connected)
                    {
                        NetworkStream clientStream = tcpClient.Tcp.GetStream();
                        ASCIIEncoding encoder = new ASCIIEncoding();
                        byte[] buffer = encoder.GetBytes(msg);
                        clientStream.Write(buffer, 0, buffer.Length);
                        clientStream.Flush();
                    }
                }
            }).Start();
        }

      
        //used to close down all tcp connections
        public void Close()
        {
            foreach (var client in AllClients)
            {
                client.Value.Tcp.Close();
            }
        }
    }

//MyTcpClent is just a wrapper to hold updates of a tcp client connection

 public class MyTcpClient
    {
        public MyTcpClient(TcpClient client)
        {
            Tcp = client;
            LastUpdate = DateTime.Now;
        }
        public TcpClient Tcp { get; set; }
        public DateTime LastUpdate { get; set; }
    }

Friday, May 25, 2012

Public IP Address Finder in C#

This is a task i have been working on to find out the public ip of a computer running behind firewall or NAT.
It uses the trace route method using ping class and then filter out local IP address using regex and find the first available public IP and try to send it as an email, email part is not shown.

 public class IPFinder
    {
        internal void MyPublicIPAndSend()
        {
            Console.WriteLine("Wait finding Public IP...");
            var firstPublicIP = Traceroute("www.google.com").Where(r => !isIPLocal(r)).FirstOrDefault();
            if (firstPublicIP != null)
                SendEmail("My Public IP", firstPublicIP.ToString());

        }


        private bool isIPLocal(IPAddress ipaddress)
        {
            // find if ip is localhost
            // find if ip starts with 10.
            //find if ip falls in 172.1 to 172.31
            //find if ip is 192.168..
            var regEx = new Regex(@"(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)");
            return regEx.Match(ipaddress.ToString()).Success;
        }

        private IPAddress[] Traceroute(string ipAddressOrHostName)
        {
            List result = new List();
            //resolve name to ip
            IPAddress ipAddress = Dns.GetHostEntry(ipAddressOrHostName).AddressList[0];
            using (Ping pingSender = new Ping())
            {
                PingOptions pingOptions = new PingOptions();
                byte[] bytes = new byte[2];
                pingOptions.DontFragment = true;
                pingOptions.Ttl = 1;
                //30 hops just to safe guard infinite loop
                int maxHops = 30;
                for (int i = 1; i < maxHops + 1; i++)
                {
                    //send icmp echo to ipAddress with timout 5000 ms
                    PingReply pingReply = pingSender.Send(
                        ipAddress,
                        5000,
                        bytes, pingOptions);
                    result.Add(pingReply.Address == null ? string.Empty : pingReply.Address.ToString());
                    // keep looping until pingreply is success, means reached destination
                    if (pingReply.Status == IPStatus.Success)
                    {
                        break;
                    }
                    pingOptions.Ttl++;
                }
            }
            IPAddress temp = IPAddress.Parse("127.0.0.1");
            return result.Where(r => IPAddress.TryParse(r, out temp)).Select(r => IPAddress.Parse(r)).ToArray();
        }

        private bool SendEmail(string subject, string body)
        {
            Console.WriteLine(subject);
            Console.WriteLine(body);
            return true;

        }




    }

Network Interface details using .Net

I want to show All my PC's IP Addresses with their subnet masks. this .net don't have any property called subnet mask but it has IPv4Mask property that i used.


 NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface Interface in Interfaces)
            {
                if (Interface.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
                Console.WriteLine(Interface.Description);
                UnicastIPAddressInformationCollection UnicastIPInfoCol = Interface.GetIPProperties().UnicastAddresses;
                foreach (UnicastIPAddressInformation UnicatIPInfo in UnicastIPInfoCol)
                {
                    Console.WriteLine("\tIP Address is {0}", UnicatIPInfo.Address);
                    Console.WriteLine("\tSubnet Mask is {0}", UnicatIPInfo.IPv4Mask);
                }
            }

Trace Route using .Net Framwrok

I was working on a task where i need to work with trace route command if ICMP and in .net i was searching for any managed method of doing so, this is what i came across it seems like a simple and good approach towards trace route using .net

public string Traceroute(string ipAddressOrHostName)

{

    IPAddress ipAddress = Dns.GetHostEntry(ipAddressOrHostName).AddressList[0];

    StringBuilder traceResults = new StringBuilder();



    using(Ping pingSender = new Ping())

    {

        PingOptions pingOptions = new PingOptions();

        Stopwatch stopWatch = new Stopwatch();

        byte[] bytes = new byte[32];



        pingOptions.DontFragment = true;

        pingOptions.Ttl = 1;

        int maxHops = 30;



        traceResults.AppendLine(

            string.Format(

                "Tracing route to {0} over a maximum of {1} hops:",

                ipAddress,

                maxHops));


        traceResults.AppendLine();


        for(int i = 1; i < maxHops + 1; i++)

        {

            stopWatch.Reset();

            stopWatch.Start();

            PingReply pingReply = pingSender.Send(

                ipAddress,

                5000,

                new byte[32], pingOptions);



            stopWatch.Stop();


            traceResults.AppendLine(

                string.Format("{0}\t{1} ms\t{2}",

                i,

                stopWatch.ElapsedMilliseconds,

                pingReply.Address));


            if(pingReply.Status == IPStatus.Success)
            {
                traceResults.AppendLine();

                traceResults.AppendLine("Trace complete."); break;

            }


            pingOptions.Ttl++;

        }


    }


    return traceResults.ToString();
}

Wednesday, May 23, 2012

Tifflib Convert multipage Tiffs to a single stitched jpeg image

I was facing issues reading 8 bit tiff files using .net GDI+ as it do not support all Tiff formats so i opt to use tifflib(an open source library to manipulate tiff files) to read the tiff images and create a 16bit tiff image from it and then create a single stitched jpeg image. converting tiffs to jpeg is not ideal because jpeg will be very large in size but i have done this because in silverlight we have no support to display tiff natively. 

Hope this will help the others

 public bool convertTiffToJpg(string sourceFile, string targetFile)
        {

            bool response = false;

            try
            {

                // Get individual Images from the original image
                //Image sourceImage = Bitmap.FromFile(sourceFile,true);
                Image sourceImage = getBitmap8Bit(sourceFile);

                var total = sourceImage.GetFrameCount(FrameDimension.Page);
                var pageNumbers = Enumerable.Range(0, total).ToArray();
                Image[] sourceImages = new Image[pageNumbers.Length];
                for (int i = 0; i < pageNumbers.Length; i++)
                {
                    sourceImage.SelectActiveFrame(FrameDimension.Page, pageNumbers[i]);
                    float width = sourceImage.Width;
                    float height = sourceImage.Height;
                    ResizeImage(1024, sourceImage.Height, ref width, ref height);

                    using (var returnImage = new Bitmap(sourceImage, (int)width, (int)height))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            returnImage.Save(ms, ImageFormat.Jpeg);
                            sourceImages[i] = Image.FromStream(ms);
                        }
                    }
                }
                var p = new System.Collections.ArrayList();
                p.Add(Color.Black);
                p.Add(Color.Gray);
                p.Add(Color.LightGray);
                p.Add(Color.DarkGray);
                p.Add(Color.White);
                PaletteQuantizer quantizer = new PaletteQuantizer(p);
                //OctreeQuantizer quantizer = new OctreeQuantizer(2,2);
                //var quantizer = new WuQuantizer();
                // Merge individual Images into one Image
                var totalHeight = sourceImages.FirstOrDefault().Height * total;
                var totalWidth = sourceImages.FirstOrDefault().Width;
                using (var finalImage = new Bitmap(totalWidth, totalHeight))
                {

                    using (var g = Graphics.FromImage(finalImage))
                    {
                        g.InterpolationMode = InterpolationMode.Low;
                        g.PixelOffsetMode = PixelOffsetMode.HighSpeed;

                        // All other pages
                        for (int i = 0; i < pageNumbers.Length; i++)
                        {
                            g.DrawImage(sourceImages[i], new Point(0, sourceImages[i].Height * i));
                        }
                    }

                    //finalImage.MakeTransparent(Color.White);
                    using (var toout = quantizer.Quantize(finalImage))
                    {
                        ImageCodecInfo Codec = ImageCodecInfo.GetImageEncoders().Where(codec => codec.FormatID.Equals(ImageFormat.Png.Guid)).FirstOrDefault();
                        toout.Save(targetFile, Codec, GetCodedParams(null));
                    }

                }

                response = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return response;
        }

 private static Image getBitmap8Bit(string inputName)
        {

            Encoder enc = Encoder.SaveFlag;
            EncoderParameters ep = new EncoderParameters(1);
            ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);
            ImageCodecInfo info = GetEncoderInfo();
            foreach (ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders())
                if (ice.MimeType == "image/tiff")
                    info = ice;

            MemoryStream ms = new MemoryStream();
            Bitmap result = null;
            using (Tiff tif = Tiff.Open(inputName, "r"))
            {
                short dirs = tif.NumberOfDirectories();

                for (int page = 0; page < dirs; page++)
                {
                    if (tif.SetDirectory((short)page))
                    {
                        FieldValue[] value = tif.GetField(TiffTag.IMAGEWIDTH);
                        int width = value[0].ToInt();

                        value = tif.GetField(TiffTag.IMAGELENGTH);
                        int height = value[0].ToInt();

                        int imageSize = height * width;
                        int[] raster = new int[imageSize];

                        if (tif.ReadRGBAImage(width, height, raster))
                        {
                            var bitmap = new Bitmap(width, height);
                            for (int i = 0; i < bitmap.Width; ++i)
                                for (int j = 0; j < bitmap.Height; ++j)
                                    bitmap.SetPixel(i, j, getSample(i, j, raster, width, height));
                            if (result == null)
                            {
                                result = bitmap;
                                result.Save(ms, info, ep);
                                ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
                            }
                            else
                            {
                                result.SaveAdd((bitmap as Image), ep);
                            }
                        }
                    }
                }
            }
            ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
            result.SaveAdd(ep);
            return Image.FromStream(ms);


        }

Sunday, May 20, 2012

ASP.Net MVC Views and Server Tags

ASP.Net MVC normal

<%   --- used to place .net code if else conditions etc --- %>
<%  Response.Write(str) %>  is equals to <%= str %>  // this is kind of a shortcut of Response.Write in MVC

now the problem is to precent plain string to be injected in response. in asp.net mvc3 we used <%= Html.Encode(str) %> to prevent script injection etc.. but in asp.net mvc 4 a new syntax is introduced as shortcut to Response.Write and Html.Encode, <%: str %>

ASP.Net MVC razor

@{ --- place if else conditions multiple lines etc ---}
@--- single line of code---   can also be used as shortcut to Response.Write @str
@{ Html.RenderPartial("view") }///Render Prefix methods will not return anything but void, they directly write to the response stream.
@Html.Partial /// returns htmlstring that can be used to store in some variable to print at some latter point eg:
@{var output = Html.Partial("View",model);} // assign html to variable
@output //send html to response

Thursday, May 10, 2012

Change Image Url in ASP.Net using HttpModule to point to some CDN

This is something i have created to change the image urls at runtime to point those url at some CDN server instead of my own server.
What i have done is simply intercept the a page if it ends with .aspx and them apply filter using my own created stream that will check the html markup and replace image url to CDN url.


ASPX Code:
 
 or even you can use 
 
 
HttpModule Code: 
  
public class CDNImageModule : IHttpModule
    {
        public void Dispose()
        {

        }
        public void Init(HttpApplication context)
        {
                context.BeginRequest += (o, e) =>
                {
                    if (context.Request.RawUrl.EndsWith(".aspx"))
                    {
                        var _watcher = new StreamWatcher(context.Response.Filter);
                        context.Response.Filter = _watcher;
                    }
                };
        }
    }

    public class StreamWatcher : Stream
    {

        public StreamWatcher(Stream sink)
        {
            _sink = sink;
        }

        private Stream _sink;

        #region Properites

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            _sink.Flush();
        }

        public override long Length
        {
            get { return 0; }
        }

        private long _position;
        public override long Position
        {
            get { return _position; }
            set { _position = value; }
        }

        #endregion

        #region Methods

        public override int Read(byte[] buffer, int offset, int count)
        {
            return _sink.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return _sink.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            _sink.SetLength(value);
        }

        public override void Close()
        {
            _sink.Close();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            byte[] data = new byte[count];
            Buffer.BlockCopy(buffer, offset, data, 0, count);
            string html = System.Text.Encoding.Default.GetString(buffer);

            TransformString(ref html);

            byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
            _sink.Write(outdata, 0, outdata.GetLength(0));
        }

        #endregion


        void TransformString(ref string input)
        {

            string regExPatternForImgTags = "]* src=\\\"([^\\\"]*)\\\"[^>]*>"; //this will match all the  tags with src attribute, you may need to extend this. 

            MatchEvaluator evaluator = new MatchEvaluator(RewriteImageSrc);


            input = Regex.Replace(input, regExPatternForImgTags, evaluator);


        }

        public static string RewriteImageSrc(Match match)
        {
            return match.Value.Replace("src=\"", "src=\"http://img.mydomain.com/");

        }
}