Paul blog

Explaining thoughts and findings is a great way to learn

July 2009 - Posts

How can we convert a local path to a UNC path in c#?

Uniform Naming Convention (UNC): According to wiki, UNC specifies a common syntax to describe the location of a network resource, such as a shared file, directory, or printer in Windows OS.

In client-server development, we  can send a server path to its clients as UNC path. Therefore, those clients can access resources from the server. The UNC syntax for Windows systems has the generic form: \\ComputerName\SharedFolder\Resource. However, the safe side is using IP instead of computer name like \\IP\SharedFolder\Resource. Here we are going to see how we can convert a local path (say d:\razan\\x.zip') to its UNC-name ( say '\\192.168.1.56 \razan\x.zip').

Why cannot we use string concatenation to do so?

The shared folder or drive can be shared as something other than the folder name/drive letter. Moreover, it is possible to have one-to-many mapping between local paths and UNC paths.

To implement this functionality, I have written the following class named UNCHelper.

   1: class UNCHelper
   2: {
   3:     public static string ConvertLocalFilePathsToUNCPath(string fileName, string sharedFolderpath)
   4:     {
   5:         string strPath = fileName.Substring(sharedFolderpath.Length);
   6:         string sharedFolderPathInUNC = ConvertLocalFolderPathToIPBasedUNCPath(sharedFolderpath);
   7:         string networkPath = sharedFolderPathInUNC + strPath;
   8:         return networkPath;
   9:     }
  10:  
  11:     public static string ConvertLocalFolderPathToIPBasedUNCPath(string localFolderName)
  12:     {
  13:         string ipBasedUNCPath = string.Empty;
  14:  
  15:         ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT Name FROM Win32_share WHERE path ='" + localFolderName.Replace("\\", "\\\\") + "'");
  16:         ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get();
  17:         if (managementObjectCollection.Count != 0)
  18:         {
  19:             foreach (ManagementObject item in managementObjectCollection)
  20:             {
  21:                 String ComputerName = ReturnMachineIP().ToString();// use  Dns.GetHostName(); for computername instead of IP
  22:                 ipBasedUNCPath = item["Name"] as String;
  23:                 ipBasedUNCPath = "\\\\" + ComputerName + "\\" + ipBasedUNCPath;
  24:                 return ipBasedUNCPath;
  25:             }
  26:         }
  27:         return ipBasedUNCPath;
  28:     }
  29:  
  30:     private static IPAddress ReturnMachineIP()
  31:     {
  32:         String hostName = Dns.GetHostName();
  33:         IPHostEntry ipEntry = Dns.GetHostEntry(hostName);
  34:         IPAddress[] addr = ipEntry.AddressList;
  35:         IPAddress ipV4 = null;
  36:         foreach (IPAddress item in addr)
  37:         {
  38:             if (item.AddressFamily == AddressFamily.InterNetwork)
  39:             {
  40:                 ipV4 = item;
  41:                 break;
  42:             }
  43:  
  44:         }
  45:         if (ipV4 == null)
  46:         {
  47:             throw new ApplicationException("You have no IP of Version 4.Server can not run witout it");
  48:         }
  49:         return ipV4;
  50:     }     
  51: }

ManagementObjectSearcher is the class that is commonly used to query disk drives, network adapters, processes, shared folder and many more management objects on a system. To test the code you can use the following line:

   1: Console.WriteLine( UNCHelper.ConvertLocalFilePathsToUNCPath("F:\\clustershare\\ razan_3.evp","F:\\clustershare"));

Here clustershare is the shared folder name. It has been tested in Windows XP and Windows Vista.

Hope this will save some of your time.

Posted: 07-24-2009 9:27 PM by Razan | with no comments
Filed under: , ,
Testing server whether it is reachable or not in c#

In client server development, we need this feature in many situations including:

  • When client starts before server, it should periodically check whether server is UP or not. As soon as it gets server is up, it will connect with it to do its own business.
  • Sometimes network between server and client can be broken and to reestablish this you can use reachability testing.

This technique can be used in WCF, .net remoting and socket programming. I have used this technique in several applications. Here testing reach ability is done by asynchronous socket programming with timeout for better performance. You can call isServerUp method at certain inteval according to your requirement. The following method checks whether server is reachable or not. If the server is reachable, It indicates that the network and server is ok and we can start doing business with server  

   1: public static bool isServerUp(string ip, int port, int timout)
   2:        {
   3:            IPAddress validIP;
   4:            if (IPAddress.TryParse(ip, out validIP))
   5:            {
   6:                IPEndPoint remoteEndPoint = new IPEndPoint(validIP, port);
   7:                bool fg = TimeOutSocket.Connect(remoteEndPoint, timout);
   8:                return fg;
   9:            }
  10:            else
  11:            {
  12:                return false;
  13:            }
  14:  
  15:        }

 You will notice that neither of the two classes, System.Net.Sockets.TcpClient nor System.Net.Sockets.Socket has a timeout to connect a socket. I mean a timeout you can set. .NET Sockets do not provide a Connect Timeout when calling the Connect or BeginConnectmethod while establishing a Synchronous or Asynchronous socket connection. Instead, connect is forced to wait a very long time before an Exception is thrown if the server it tried to connect to is not listening or if there is any network error. The default timeout is 20 - 30 seconds. There is an option in socket library named SocketOptionName.SendTimeout, which is used for timeouts on Send data not initial connects. To get this functionality, I have implemented the following class named TimeOutSocket.

   1: class TimeOutSocket
   2:    {
   3:        private static bool IsConnectionSuccessful = false;
   4:        private static Exception socketexception;
   5:        private static ManualResetEvent TimeoutObject = new ManualResetEvent(false);
   6:  
   7:  
   8:        public static  bool  Connect(IPEndPoint remoteEndPoint, int timeoutMSec)
   9:        {
  10:            TimeoutObject.Reset();
  11:            socketexception = null;  
  12:  
  13:            string serverip = Convert.ToString(remoteEndPoint.Address);
  14:            int serverport = remoteEndPoint.Port;           
  15:            TcpClient tcpclient = new TcpClient();
  16:        
  17:            tcpclient.BeginConnect(serverip, serverport, new AsyncCallback(CallBackMethod), tcpclient);
  18:  
  19:            if (TimeoutObject.WaitOne(timeoutMSec, false))
  20:            {
  21:                if (IsConnectionSuccessful)
  22:                {
  23:                    tcpclient.Close();
  24:                    return true;
  25:                }
  26:                else
  27:                {
  28:                    tcpclient.Close();
  29:                    return false;
  30:                }
  31:            }
  32:            else
  33:            {
  34:                tcpclient.Close();
  35:                return false;
  36:            }
  37:        }
  38:        private static void CallBackMethod(IAsyncResult asyncresult)
  39:        {
  40:            try
  41:            {
  42:                IsConnectionSuccessful = false;
  43:                TcpClient tcpclient = asyncresult.AsyncState as TcpClient;
  44:             
  45:                if (tcpclient.Client != null)
  46:                {
  47:                    tcpclient.EndConnect(asyncresult);
  48:                    IsConnectionSuccessful = true;
  49:                }
  50:            }
  51:            catch (Exception ex)
  52:            {
  53:                IsConnectionSuccessful = false;
  54:                socketexception = ex;
  55:            }
  56:            finally
  57:            {
  58:                TimeoutObject.Set();
  59:            }
  60:        }
  61:    }

Here ManualResetEvent plays the main role to implement this. It has a method WaitOne which has an overload WaitOne(TimeSpan,Boolean). According to MSDN, aitOne(TimeSpan, Boolean) blocks the current thread until the current instance receives a signal, using a TimeSpan to measure the time interval  and specifying whether to exit the synchronization domain before the wait.

So in the main thread, we call TimeoutObject.WaitOne(timeoutMSec, false) to block the main thread until timeout or till the signal has been  got using TimeoutObject.Set(). When waitone faces timeout, then it returns timeout exception. Otherwise socket is successfully connected or it faced any network error.

Here BeginConnect of tcpclient is used because this method does not block. After calling BeginConnect, we wait using waitone. If BeginConnect does not complete operation within timeout, then waitone will signal and TimeoutException is returned. IfBeginConnect does complete operation within timeout, then it will signal ManualResetEvent using TimeoutObject.Set() from theCallBackMethod which we passed as delegate in BeginInvoke that references the CallBackMethod to invoke when the operation is complete.

Thanks for reading this write up. I hope that this write up will be helpful for some people. If you guys have any questions, I would love to answer.

Posted: 07-18-2009 1:46 PM by Razan | with no comments
Filed under: , ,