Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#

Whois Client with .NET

Rate me:
Please Sign up or sign in to vote.
3.94/5 (12 votes)
8 Sep 2010CDDL3 min read 59K   1.8K   40   11
A little class to query whois servers

Introduction

I'm working on a bookmarks manager, and I wanted to be able to make whois queries for any domain in my bookmarks. So I searched for any class or tool in .NET that can do that. However, I did not meet with success and decided to build my own. Let me explain how I've done that.

Background

My first (and only) idea was to look at the source code of the GNU/Whois client (thanks to Open Source), and adapt it to my needs. Here is the result.

Architecture

I store a list of Top-Level Domains (TLD), with the Whois server to query in a *.ini file, as shown below (I provide my own list on top of this page):

[Servers]
.br.com=whois.centralnic.net
.cn.com=whois.centralnic.net
.eu.org=whois.eu.org
.com=whois.crsnic.net
.net=whois.crsnic.net
.org=whois.publicinterestregistry.net
.edu=whois.educause.net
.gov=whois.nic.gov


[...]

I made this list using the original list found in the source package of the GNU client, and my own searches.

If you prefer using another way to store TLD and Whois servers, you can use XML or AppSettings, so you don't need to have a class for handling INI files. I personally use *.ini files because it's more flexible for my project.

Using the Code

The client is contained in just two files: one for the EventArgs, and one for the query. This is the content of the WhoisEventArgs class:

C#
using System;

namespace WhoisClient
{
    /// <summary>
    /// Arguments for the whois system    
    /// </summary>
    public class WhoisEventArgs : EventArgs
    {
        private string _url, _message, _tld, _targetServer;

        /// <summary>
        /// URL to query
        /// </summary>
        public string Url { get { return _url; } }

        /// <summary>
        /// Message returned by the whois server
        /// </summary>
        public string Message { get { return _message; } }

        /// <summary>
        /// TLD of the current query
        /// </summary>
        public string TLD { get { return _tld; } }

        /// <summary>
        /// Hostname of the server queried
        /// </summary>
        public string TargetServer { get { return _targetServer; } }

        /// <summary>
        /// Initialize a new instance of the class with the specified parameters
        /// </summary>
        /// <param name="url">Url to query</param>
        /// <param name="tld">Top Level Domain</param>
        /// <param name="targetServer">Server handling the query</param>
        /// <param name="message">Message linked to the event</param>
        public WhoisEventArgs
            (string url, string tld, string targetServer, string message)
        {
            _url = url;
            _tld = tld;
            _targetServer = targetServer;
            _message = message;
        }
    }
}

Now, the code of the main class:

C#
using System;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace WhoisClient
{
    /// <summary>
    /// Allows to make a whois query
    /// </summary>
    public class WhoisRequest
    {
        private string _url, 
                       _domain, 
                       _tld, 
                       _targetServer, 
                       _defaultTargetServer = "whois.arin.net" // Can be modified;

        /// <summary>
        /// Url to query
        /// </summary>
        public string Url { get { return _url; } }

        /// <summary>
        /// Get or set the default server to query, if no one has returned any result
        /// </summary>
        public string DefaultTargetServer 
            { get { return _defaultTargetServer; } 
            set { _defaultTargetServer = value; } }

        /// <summary>
        /// Fired when a response is received from the server
        /// </summary>
        public event EventHandler<WhoisEventArgs> ResponseReceived;

        /// <summary>
        /// Fired when connection closed
        /// </summary>
        public event EventHandler ConnectionClosed;

        /// <summary>
        /// Initialize a new instance of the class
        /// </summary>
        /// <param name="url"></param>
        public WhoisRequest(string url)
        {
            _url = url;

            Uri u = null;

            try
            {
                u = new Uri(url);
            }
            catch(Exception ex)
            {
                throw new Exception(ex.Message);
            }

            if (u != null)
            {
                Initialize(u);
            }
        }

        /// <summary>
        /// Initialize a new instance of the class
        /// </summary>
        /// <param name="url"></param>
        public WhoisRequest(Uri url)
        {
            Initialize(url);
        }

        /// <summary>
        /// Do job
        /// </summary>
        void Initialize(Uri url)
        {
            if (url != null)
            {
                _url = url.ToString();

                _domain = url.DnsSafeHost;

                if (_domain.IndexOf(".") < _domain.Length - 4)
                {
                    _domain = _domain.Substring(_domain.IndexOf(".") + 1);
                }

                _tld = _domain.Substring(_domain.LastIndexOf("."));
                _targetServer = Global.Global.WhoisServersConf.GetValue
                    ("Servers", _tld, typeof(string)).ToString();

                if (_targetServer == "" || _targetServer == null)
                {
                    _targetServer = _defaultTargetServer;
                }
            }
        }

        /// <summary>
        /// Send the query
        /// </summary>
        public void GetResponse()
        {
            BackgroundWorker bw = new BackgroundWorker();

            bw.DoWork += new DoWorkEventHandler(bw_DoWork);

            bw.RunWorkerAsync();
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            string response = DoRequest(_targetServer);

            StringReader sr = new StringReader(response);

            if (response.Contains("Whois Server:"))
            {
                string newTargetServer = "";

                while (newTargetServer == "")
                {
                    string line = sr.ReadLine().Trim();

                    if (line.StartsWith("Whois Server:"))
                    {
                        newTargetServer = line.Substring(14);

                        DoRequest(newTargetServer);
                    }
                }
            }

            OnConnectionClosed();
        }

        string DoRequest(string server)
        {
            WhoisEventArgs wea = new WhoisEventArgs(
                _url,
                _tld,
                server,
                "Trying to connect to " + server + " (query : " + _domain + ") ...\r\n"
            );

            OnResponseReceived(wea);

            string response = "";

            TcpClient client = null;

            try
            {
                client = new TcpClient(server, 43);
            }
            catch (Exception ex)
            {
                wea = new WhoisEventArgs(
                    _url,
                    _targetServer,
                    _targetServer,
                    "Connection to server " + server + " failed : \r\n" + 
                            ex.Message + "\r\n\r\n"
                );

                OnResponseReceived(wea);
            }

            if (client != null)
            {
                string formatedDomain = _domain + "\r\n";
                byte[] byteUrl = Encoding.ASCII.GetBytes(formatedDomain);

                Stream s = client.GetStream();

                bool error = true;

                try
                {
                    wea = new WhoisEventArgs(
                        _url,
                        _targetServer,
                        _targetServer,
                        "Connection to server " + _targetServer + 
                        " established. Executing query ...\r\n\r\n"
                    );

                    OnResponseReceived(wea);

                    s.Write(byteUrl, 0, formatedDomain.Length);

                    error = false;
                }
                catch (Exception ex)
                {
                    wea = new WhoisEventArgs(
                        _url,
                        _targetServer,
                        _targetServer,
                        "Unable to perform query : \r\n" + ex.Message + "\r\n\r\n"
                    );

                    OnResponseReceived(wea);
                }

                if (!error)
                {
                    StreamReader sr = new StreamReader(s, Encoding.ASCII);

                    response = sr.ReadToEnd() + "\r\n";

                    sr.Close();
                    sr.Dispose();
                    sr = null;

                    wea = new WhoisEventArgs(
                        _url,
                        _targetServer,
                        _targetServer,
                        response
                    );

                    OnResponseReceived(wea);
                }

                s.Close();
                s.Dispose();
                s = null;

                client.Close();
                client = null;
            }

            return response;
        }

        void OnResponseReceived(WhoisEventArgs e)
        {
            if (ResponseReceived != null)
            {
                ResponseReceived(this, e);
            }
        }

        void OnConnectionClosed()
        {
            if (ConnectionClosed != null)
            {
                ConnectionClosed(this, null);
            }
        }
    }
}

Explanation

The WhoisEventArgs class is used to pass some arguments to the main project (or the console or MessageBox, maybe).

When we want to perform a request, we use this code:

C#
WhoisRequest req = new WhoisRequest("http://www.codeproject.com/");

req.ResponseReceived += new EventHandler<WhoisEventArgs>(req_ResponseReceived);
req.ConnectionClosed += new EventHandler(req_ConnectionClosed);

req.GetResponse();

So what's going on when we call this code ?

  • If we pass a URI in the ctor, directly call the Initialize (Uri uri) method. If we pass a string, try to convert it to a valid URI and then call the Initialize (Uri uri) method.
  • When we have our so called URI, we can extract from the *.ini file (or whatever you want, where you have saved your list) the whois server corresponding to the TLD of that URI.

    Note: In my example, I use my own INI parser which I'll probably post to The Code Project in the near future (the line "Global.Global.WhoisServersConf.GetValue([...])").

    Then we wait for the call of the GetResponse() method.

  • When this method is called, the hard work starts.

    Note: I use a BackgroundWorker there because, once again, it's more flexible for my own project. The worker is optional, you can just adapt to suit your needs.

  • We make a first query.
  • If that query returns a result containing the words "Whois Server:", then the server we queried is not the actual server handling the domain of the URL we're checking. So we make a second query against the server indicated in the response.

Final Words

I hope this will be helpful. This is my first contribution to The Code Project, and I know that it won't be the last.

I think many things in that little class can be improved, so I wait for your comments.

Points of Interest

If we want to slightly customize the way to do queries, we can, like the GNU client, use some options, as removing advertisement message or server description, just show the final response when we haven't queried the right server for the first time, etc.

History

  • 13/02/2008 - 1.0: First publication
  • 06/09/2010 - Updated source code

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
PapyRef16-Aug-12 4:15
professionalPapyRef16-Aug-12 4:15 
GeneralI need it but in VB .NET Help.... Pin
ingenvzla31-May-11 5:25
ingenvzla31-May-11 5:25 
NewsNew Source Code available Pin
Tino Hager10-Sep-10 10:18
Tino Hager10-Sep-10 10:18 
GeneralMy vote of 1 Pin
Sopholos25-Jan-10 23:06
Sopholos25-Jan-10 23:06 
GeneralMy vote of 1 Pin
Mailmaster25-Jan-10 22:48
Mailmaster25-Jan-10 22:48 
GeneralDumb question from newbie Pin
Victoria Rowe28-Mar-09 20:59
Victoria Rowe28-Mar-09 20:59 
Generalnot with full information Pin
AtulGkp13-Oct-08 2:22
AtulGkp13-Oct-08 2:22 
GeneralRe: not with full information Pin
Athalia17-Oct-08 6:49
Athalia17-Oct-08 6:49 
WhoisRequest req = new WhoisRequest("http://www.codeproject.com/");
req.ResponseReceived += new EventHandler<whoiseventargs>(req_ResponseReceived);
req.ConnectionClosed += new EventHandler(req_ConnectionClosed);
req.GetResponse();

You call GetResponse before setting event handlers Smile | :)
AnswerRe: not with full information Pin
Mauro197129-Oct-08 3:34
Mauro197129-Oct-08 3:34 
GeneralRe: not with full information Pin
Athalia6-Nov-08 5:58
Athalia6-Nov-08 5:58 
GeneralThank you Pin
amgadhs6-Oct-08 0:14
amgadhs6-Oct-08 0:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.