Internet Protocol Suite

.Internet Protocol Suite
IP Addresses | Ports | URIs | TCP/IP Protocols | HTTP | FTP | SMTP | DNS | WebClient Screen Scraper

"The .NET framework includes support for the Internet Protocol Suite as classes defined in the System.Net and System.Net.Sockets namespaces. Support includes IPv4 and IPv6 addressing, proxies, security, diagnostics, and socket level access."

.TCP/IP Protocol Suite
Internet (TCP/IP) Protocol Suite

The Internet Protocol Suite is one of the most commonly used network protocols. It is also referred to as TCP/IP, because its most important protocols, the Transmission Control Protocol (TCP) and the Internet Protocol (IP), were the first networking protocols defined in this suite. TCP/IP was developed by the Defense Advanced Research Projects Agency (DARPA) in the 1970's. A primary goal of the time was to create a system for "open-architecture interconnection", which was a way to connect computers comprised of different hardware and different operating systems. The researchers designed a system where computers located on the edge of the network, on the end nodes, would control the transmission and routing logic for the data. Today these computers are called routers.




IP Addresses

Routing data on a computer network requires each computer to be uniquely identified with a Media Access Control address (MAC address) which is assigned to the computer's network interface. The process of tying a MAC address to an IP address depends upon the type of IP address. The Internet Corporation for Assigned Names and Numbers (ICANN) coordinates the usage of IP addresses through its Internet Assigned Numbers Authority (IANA). ICANN also publishes Internet related information, such as their Who Runs the Internet? infographic and their IPV6 Fact Sheet.

  1. IPV4 - Currently the dominant IP addressing system.
    • 32 bits wide, e.g. 101.102.103.104
    • Uses Address Resolution Protocol (ARP) - for resolution of MAC addresses to IP addresses.
    • In Dos, Enter: arp -a to get list of MAC addresses with associated IP addresses.
  2. IPV6 - The newer IP addressing system.
    • 128 bits wide, e.g. [4CA0:FFFF:176A:E4A3:4FC5:54FA:43AD:6D32]
    • Uses Neighbor Discovery Protocol (NDP) -for resolution of MAC addresses to IP addresses.

The IPAddress class can be used to represent an IP address in either IPV4 or IPV6:

IPV4 and IPV6 Addresses

// Check OS Support for IP Address Versions
Console.WriteLine("\r\nSupportsIPv4: " + Socket.OSSupportsIPv4);
Console.WriteLine("SupportsIPv6: " + Socket.OSSupportsIPv6);

// IPV4 Address
IPAddress a1 = new IPAddress(new byte[] { 101, 102, 103, 104 });
IPAddress a2 = IPAddress.Parse("101.102.103.104");
Console.WriteLine(a1.AddressFamily); // Prints: InterNetwork

// IPV6 Address
IPAddress a3 = IPAddress.Parse                                         
        ("[4CA0:FFFF:176A:E4A3:4FC5:54FA:43AD:6D32]");
Console.WriteLine(a3.AddressFamily); // Prints: InterNetworkV6   
// Check OS Support for IP Address Versions
Console.WriteLine("\r\nSupportsIPv4: " + Socket.OSSupportsIPv4);
Console.WriteLine("SupportsIPv6: " + Socket.OSSupportsIPv6);

// IPV4 Address
IPAddress a1 = new IPAddress(new byte[] { 101, 102, 103, 104 });
IPAddress a2 = IPAddress.Parse("101.102.103.104");
Console.WriteLine(a1.AddressFamily); // Prints: InterNetwork

// IPV6 Address
IPAddress a3 = IPAddress.Parse                                         
        ("[4CA0:FFFF:176A:E4A3:4FC5:54FA:43AD:6D32]");
Console.WriteLine(a3.AddressFamily); // Prints: InterNetworkV6   

Top




Ports

Once a computer has been uniquely identified with an IP address, the transmitted data is accepted through the computer's TCP and UDP ports. Each computer has a total of 65,535 TCP Ports and another 65,535 UDP ports. The port numbers an application uses is registered with the IANA. See the IANA Port Number Registry for a complete listing of port number assignments. The IANA has divided the port numbers into three ranges:

  1. System Ports (0-1023)
  2. User Ports (1024-49151)
  3. Dynamic and/or Private Ports (49152-65535)

The ports in the (49152-65535) range are used for testing or small-scale deployment. Some of the most frequently used port assignments include:

  • FTP = 20, 21
  • SSH = 22
  • Telnet = 23
  • SMTP = 25
  • HTTP = 80
  • POP3 = 110
  • HTTPS = 443

Note: Firewalls block ports, so in business environments typically only a few ports are open by default.

The following program scans the TCP system ports (0-1023) and reports which ports are open. The scans are performed using a Parallel.For loop, results stored in a concurrent dictionary, and then processed with a LINQ query to extract and report the open ports.

.Port Scanner Checking for Open System Ports
Port Scanner Checking for Open System Ports

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace PortScanner
{
    class Program
    {
        static ConcurrentDictionary<int, char> thePorts = new ConcurrentDictionary<int, char>();

        static void Main(string[] args)
        {
            int startPort = 0;
            int endPort = 1023;

            Console.Write("Scanning ");

            // Scan for Open Ports Using Parallel For Loop
            Parallel.For(startPort, endPort, i =>
            {
                TcpClient portScan = new TcpClient();
                portScan.SendTimeout = 10;
                try
                {
                    portScan.Connect("localhost", i);
                    Console.Write("O");
                    thePorts.TryAdd(i, 'O');
                }
                catch (Exception)
                {
                    Console.Write("c");
                    thePorts.TryAdd(i, 'C');
                }
            });

            // Select the Open Port Numbers
            var myQuery = from kvp in thePorts
                         where kvp.Value.Equals('O')
                         orderby kvp.Key
                         select kvp.Key;

            // Print the Open Ports
            Console.WriteLine("\n\n--- Open Ports in Range ({0} - {1}) ---", startPort, endPort);
            foreach (var port in myQuery)
            {
                Console.WriteLine("Port: {0} is OPEN", port);
            }
            Console.WriteLine();
        }
    }
}

Top



URIs

The Uniform Resource Identifier (URI) standards are defined by The Internet Engineering Task Force (IETF) under the charter of the Uniform Resource Identifiers Working Group. URIs can be classified as locators (URLs) or names (URNs), however URI and URL are commonly used as if they were synonymous. .NET uses URIs for locating resources on the Internet, on a LAN, or on a local drive. For example, .NET will convert an absolute file name (C:\myfiles\apicture.jpg) or a UNC path to a file on a LAN (\\kevinpc\shared\apicture.jpg) to a URI.

The Uri Class defines the properties and methods for handling URIs, including parsing, comparing, and combining. The Uri class properties are read-only. The UriBuilder Class provides a convenient way to modify the contents of a Uri instance without creating a new Uri instance for each modification. Also, the UriBuilder properties provide read/write access to the read-only Uri properties so that they can be modified. A useful helper method of the URI class is the Uri.GetComponents Method also allows you to get the specified components of the current instance in different formats. Another helper method is the EscapeUriString which converts all the characters in a URI string with an ASCII value greater than 127 to hexadecimal.

The URI class allows a URI to be broken down into component parts, which is useful when validating the format of a URI string. These component parts are obtained through the properties:

  • Scheme
  • Host
  • Port
  • Query
  • Fragment
  • Authority

The following program creates a URI from a string then writes the URI in different formats. It also writes the individual components of the URI as well as the predicate values for the URI.

.URI Creation, Formatting, Components, and Predicates
URI Creation, Formatting, Components, and Predicates

using System;

namespace UriExample
{
    class Program
    {
        static void Main()
        {
            // Create Escaped URI
            string s = Uri.EscapeUriString("http://kcshadow.net:80/wpdeveloper/?q=q and a");
            Uri myURI = new Uri(s);

            // URIs Printed as Strings
            Console.WriteLine("\n ------ URIs Printed as Strings --------");
            Console.WriteLine("Original String : {0}", myURI.OriginalString);
            Console.WriteLine("ToString        : {0}", myURI.ToString());
            Console.WriteLine("Without Port #  : {0}\n",
                               myURI.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port,
                               UriFormat.UriEscaped));

            // URI Components
            Console.WriteLine("\n --------- URI Components --------------");
            Console.WriteLine("Scheme          : {0}", myURI.Scheme);
            Console.WriteLine("Host            : {0}", myURI.Host);
            Console.WriteLine("Port            : {0}", myURI.Port);
            Console.WriteLine("AbsolutePath    : {0}", myURI.AbsolutePath);
            Console.WriteLine("Query           : {0}", myURI.Query);
            Console.WriteLine("Fragment        : {0}", myURI.Fragment);
            Console.WriteLine("Authority       : {0}", myURI.Authority);
            Console.WriteLine("PathAndQuery    : {0}", myURI.PathAndQuery);
                       
            // URI Predicates
            Console.WriteLine("\n --------- URI Predicates --------------");
            Console.WriteLine("IsAbsoluteUri                : {0}", myURI.IsAbsoluteUri); // Prints: True
            Console.WriteLine("IsDefaultPort                : {0}", myURI.IsDefaultPort); // Prints: True
            Console.WriteLine("IsFile                       : {0}", myURI.IsFile); // Prints: False
            Console.WriteLine("myURI.IsLoopback             : {0}", myURI.IsLoopback); // Prints: False
            Console.WriteLine("IsUnc                        : {0}", myURI.IsUnc); // Prints: False
            Console.WriteLine("IsWellFormedOriginalString() : {0}", myURI.IsWellFormedOriginalString()); // Prints: True
            Console.WriteLine();
        }
    }
}

Top



TCP/IP Protocols

The Internet protocol suite abstracts the protocols and services by dividing the protocol suite into layers of general functionality. The layers at the top are logically closer to the user application, while those near the bottom are logically closer to the physical transmission of the data. Researchers have created networking models which vary from three to seven layers. Today the two commonly used models are the OSI Model which provides a greater degree of abstraction than the DARPA (a.k.a. TCP/IP) Model.

Most of the time it is convenient to write network code with a high-level protocol which targets the Application Layer. However there are situations where more primitive network coding is required to send bytes of data targeting the lower levels. The following outline shows the protocol layers with the corresponding .NET classes used for the protocol.

  1. Application Layer
    1. HTTP - Hypertext Transfer Protocol is an application protocol for distributed, collaborative, hypermedia information systems and is the foundation of data communication for the World Wide Web.
      1. WebClient - is a higher level method which performs similar logic as calling both WebRequest and WebResponse. WebClient can work with strings, byte arrays, files, and streams. WebRequest/WebResponse can only work with streams, but has some capabilities which WebClient does not, such as the ability to use cookies.

      2. WebRequest - is the abstract base class for the request/response model for accessing data from the Internet.

      3. WebResponse - is the abstract base class for the request/response model for accessing data from the Internet.

      4. HttpListener - used to create a simple HTTP protocol listener that responds to HTTP requests.
    2. FTP - File Transfer Protocol (FTP) is a standard network protocol used to transfer files from one host to another host over a TCP-based network, such as the Internet.
      1. FTP - support is provided for the FTP protocol with the FtpWebRequest and FtpWebResponse classes. These classes are derived from WebRequest and WebResponse. In most cases, the WebRequest and WebResponse classes provide all that is necessary to make the FTP request, but if you need access to the FTP-specific features exposed as properties, you can typecast these classes to FtpWebRequest or FtpWebResponse.

      2. WebClient - is a higher level method which performs similar logic as calling both WebRequest and WebResponse.

      3. WebRequest, FtpWebRequest - are classes for the request/response model for accessing data from the Internet.

      4. WebResponse, FtpWebResponse - are classes for the request/response model for accessing data from the Internet.

    3. SMTP - Simple Mail Transfer Protocol (SMTP) is an Internet standard for electronic mail (e-mail) transmission.
      1. SmtpClient - for constructing and sending email messages using SMTP.
    4. DNS - The Domain Name System (DNS) is a hierarchical distributed naming system for computers, services, or any resource connected to the Internet or a private network.
      1. Dns - for converting between domain names and addresses.
  2. Transport Layer
    1. TCP - The Transmission Control Protocol one of the core protocols of the Internet protocol suite. TCP is a connection-oriented protocol suited for applications that require high reliability, and where transmission time is relatively less critical.
      1. TCPClient - provides client connections for TCP network services.
    2. UDP - The User Datagram Protocol (UDP) is one of the core members of the Internet protocol suite. UDP is a connectionless protocol suited for applications that need fast, efficient transmission, such as games. UDP's stateless nature is also useful for servers that answer small queries from huge numbers of clients.
      1. UdpClient - provides User Datagram Protocol network services.
    3. Sockets - Socket are one of the most fundamental networking technologies which allows direct access to the Transport and Network layers. Sockets allow applications to communicate using standard mechanisms built into network hardware and operating systems. Socket technology has been used for about twenty years. There are many types of sockets, however Internet sockets are usually based on the Berkeley sockets standard.
      1. Socket - implements the Berkeley sockets interface.

The following sections provide more details with example code for these TCP/IP protocols. Some of the .NET classes support multiple protocols. For example the WebRequest and WebResponse classes can handle HTTP, FTP, and the "file:" protocols.

Top




HTTP - Hypertext Transfer Protocol

"HTTP is used to retrieve Web pages and run Web services. The use of HTTP has also been extended to general purpose communications."

HTTP is supported in .NET with the WebClient, WebRequest, WebResponse, and HttpListener classes. Beyond these classes, .NET also supports HTTP at higher levels using such technologies as WCF, ASP.NET, and Web Services. HTTP has several features which make it well-suited for business applications and service oriented architectures, such as authentication, encryption, messaging, extensible headers, cookies, and the ability to have many applications share a single IP address and port. These vital features in HTTP have been used to extend the usage of HTTP to general purpose communications. Information about HTTP extensions are on the W3C website HTTP Extension Framework.



WebClient Class

The WebClient Class is a higher level method which performs similar logic as calling both WebRequest and WebResponse. WebClient can work with strings, byte arrays, files, and streams. WebRequest/WebResponse can only work with streams. However the lower level of WebRequest/WebResponse allows more fine grained protocol control than be achieved with WebClient.

WebClient - Properties
  1. Proxy - gets or sets the proxy used by this WebClient object. To specify that no proxy should be used, set the Proxy property to the proxy instance returned by the GetEmptyWebProxy method.

  2. Credentials - contains the authentication credentials used to access a resource on a host. In most client-side scenarios, you should use the DefaultCredentials, which are the credentials of the currently logged on user. To do this, set the UseDefaultCredentials property to true instead of setting this property.

  3. UserDefaultCrendentials - set this property to true when requests made by this WebClient object should, if requested by the server, be authenticated using the default credentials of the currently logged on user.

  4. QueryString - gets or sets a collection of query name/value pairs associated with the request.

  5. ResponseHeaders - contains a WebHeaderCollection instance containing header information the WebClient receives with the response.

  6. IsBusy - gets whether a Web request is in progress.

WebClient - Methods
  1. WebClient.UploadData - Uploads a data buffer to a resource identified by a URI. The UploadData method sends the content of data to the server without encoding it. This method blocks while uploading the data. To continue executing while waiting for the server's response, use one of the UploadDataAsync methods.

  2. WebClient.UploadValuesTaskAsync - Uploads the specified name/value collection to the resource identified by the specified URI as an asynchronous operation using a task object. These methods do not block the calling thread.

WebClient - Events
  1. DownloadDataCompleted - event is raised each time an asynchronous data download operation completes. Asynchronous data downloads are started by calling the DownloadDataAsync methods.

  2. DownloadFileCompleted - event is raised each time an asynchronous file download operation completes. Asynchronous file downloads are started by calling the DownloadFileAsync methods.

  3. DownloadProgressChanged - event is raised each time an asynchronous download makes progress.

The following program uses Webclient to download two images from the Internet and display in the computer's default image viewer.

.Download from Internet Display in Default Viewer



Webclient - Download Image Files and Display with Default Viewer

using System;
using System.Net;

namespace WebclientExample
{
    class Program
    {
        static void Main()
        {
            WebClient myWebClient = new WebClient();
            myWebClient.DownloadFile("http://www.kcshadow.net/_photos/tucker1.jpg", "keh1.jpg");
            System.Diagnostics.Process.Start("keh1.jpg");

            WebClient myWebClient2 = new WebClient();
            myWebClient2.DownloadFile("http://www.kcshadow.net/_photos/sgate.jpg", "keh2.jpg");
            System.Diagnostics.Process.Start("keh2.jpg");
        }
    }
}



WebRequest and WebResponse Classes

The WebRequest/WebResponse classes are the abstract request/response classes from which protocol-specific response classes are derived. The WebRequest/WebResponse classes can perform a similar function as the WebClient class, but they allow more fine grained protocol control than be achieved with WebClient. Also some features, such as cookies, are not supported on WebClient and require the use of the WebRequest/WebResponse classes.

MSDN explains how to use the WebRequest/WebResponse classes in the article How to: Request Data Using the WebRequest Class. The following program shows a simple example of their usage in downloading an HTML file from a website.

WebRequest/WebResponse - Download HTML Page and Display in Default Viewer

using System.IO;
using System.Net;

namespace WebRequestWebResponse
{
    class Program
    {
        static void Main(string[] args)
        {
            WebRequest req = WebRequest.Create
                ("http://www.kcshadow.net/wpdeveloper/?q=networking");               
            req.Proxy = null;
            using (WebResponse res = req.GetResponse())
            using (Stream s = res.GetResponseStream())
            using (StreamReader sr = new StreamReader(s))
                File.WriteAllText("network.htm", sr.ReadToEnd());

            System.Diagnostics.Process.Start("network.htm");
        }
    }
}

Top



FTP - File Transfer Protocol

The WebClient can be used for simple uploading and downloading of files. To run one of the FTP commands, set the WebRequest.Method property to one of the values defined in the WebRequestMethods.Ftp enumeration. The following program shows how to use the WebRequest class to connect to a site using FTP and get a directory listing.

FTP - Obtain Directory Listing from Site

using System;
using System.IO;
using System.Net;

namespace FTPExample
{
    class Program
    {
        static void Main()
        {
            var request = (FtpWebRequest)WebRequest.Create("ftp://ftp.thesite.com");
            request.Credentials = new NetworkCredential("username", "password");
            request.Method = WebRequestMethods.Ftp.ListDirectory;

            string fileListing="";
            using (WebResponse response = request.GetResponse())
            using (StreamReader reader = new StreamReader (response.GetResponseStream()))
                fileListing = reader.ReadToEnd();
            Console.WriteLine(fileListing);
        }
    }
}

Top



SMTP - Simple Mail Transfer Protocol

The SmtpClient class allows applications to send e-mail by using the Simple Mail Transfer Protocol (SMTP). To send an attachment, create an Attachment class and add it to the message. The SmtpClient class implementation pools SMTP connections so that it can avoid the overhead of re-establishing a connection for every message to the same server. An application may re-use the same SmtpClient object to send many different emails to the same SMTP server and to many different SMTP servers. As a result, there is no way to determine when an application is finished using the SmtpClient object and it should be cleaned up. The SmtpClient class has no Finalize method, so an application must call Dispose to explicitly free up resources.

Send Mail with SmtpClient

using System.Net;
using System.Net.Mail;

namespace smtpExample
{
    class Program
    {
        static void Main()
        {
            SmtpClient client = new SmtpClient();
            client.Credentials = new NetworkCredential("username", "password");
            client.Host = "mail.kcshadow.net";
            client.Send("holly@kcshadow.net", "tessa@kcshadow.net", "subject", "body");
        }
    }
}

Top



DNS - The Domain Name System

The Dns is a static class which converts between IP addresses and domain names. The host information from the DNS query is returned in an instance of the IPHostEntry class. If the specified host has more than one entry in the DNS database, IPHostEntry contains multiple IP addresses and aliases. The Dns class contains asynchronous methods which provide a high degree of concurrency.

Dns Class - Convert Between IP Address and Domain Names

using System;
using System.Net;

namespace dnsExample
{
    class Program
    {
        static void Main()
        {
             // Convert Domain Name to IP Address
             IPAddress theIPAddress = Dns.GetHostAddresses("www.google.com")[0];
             Console.WriteLine(theIPAddress); //Prints: 173.194.46.83

             // Convert IP Address to Domain Name
             IPHostEntry entry = Dns.GetHostEntry(theIPAddress);
             Console.WriteLine(entry.HostName); // Prints: ord08s11-in-f19.1e100.net
        }
    }
}

Top



WebClient Screen Scraper

.Screen Scraper with WebClient


"Program uses WebClient class to extract the title, meta, and anchor tags from the Webpage specified by a URL passed in as the first program argument. Extracted tags and a summary of the results are written to a file."

WebClient class is used to download the Webpage specified as the first argument on the command tail. Regular expressions are used to extract the title tag, all the meta tags, and all the anchor tags (links). The results are timestamped and appended to the file specified as the second program argument, or to file "msdefault.txt" if no file is specified. Additionally a summary of the count of each type of extract html tag is written to the file along with the programs elapsed time. Program uses the following C# features:

  1. WebClient - Used to download the Webpage into a string for processing.
  2. Regex - Regular express class used to validate URI and extract HTML tags from Webpage.
  3. FileStream - A backing store stream for the output file.
  4. TextWriter - A stream adapter for writing text.
  5. StopWatch - A diagnostics class used to measure elapsed time.
Screen Scaper to Extract HTML Tags from Webpages

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

namespace ManualSpider
{
    /*********************************************************************************
     * Name: ManualSpider                                                            *
     *                                                                               *
     * Syntax: ManualSpider URI [OutputFileName]                                     *
     * Example 1: ManualSpider www.kcshadow.net  (Output File = msdefault.txt)       *
     * Example 2: ManualSpider www.kcshadow.net kcshadow.txt                         *
     *                                                                               *
     * Description: A screen scraper that parses the webpage specified as the first  *
     *              parameter on the command tail.  Extracts the title tag, all      *
     *              meta tags and all anchor tags and writes them to an output file. *
     *              After extraction a summary of tag counts, program run time, and  *
     *              extraction data is also printed to the output file.              *
     *                                                                               *
     *********************************************************************************/
    class Program
    {
        // Validate URI pass in as first argument
        static void ProcessURI(string[] args)
        {
            // Check for URI on command tail
            if (args.Length == 0)
            {
                Console.WriteLine("\nSyntax is: ManualSpider URI OutputFileName");
                Console.WriteLine("Example:   ManualSpider www.kcshadow.net myOutputFile.txt\n");
                Environment.Exit(-1);
            }

            // Check for valid URI
            if (!Regex.Match(args[0], @"([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.IgnoreCase).Success)
            {
                Console.WriteLine("Invalid URI: {0}", args[0]);
                Environment.Exit(-1);
            }
        }


        static void Main(string[] args)
        {           
            DateTime currentTimestamp = DateTime.Now;
            string outputfileName;
            string pageHTML = default(string);
            int titleTagCount = 0;
            int metaTagCount = 0;
            int anchorTagCount = 0;

            // Start Stopwatch
            Stopwatch stopWatch1 = new Stopwatch();
            stopWatch1.Start();

            // Validate URI
            ProcessURI(args);

            Console.WriteLine("Program is running ...");

            // Check for output file name on command tail
            if (args.Length > 1)
                outputfileName = args[1];
            else
                outputfileName = "msdefault.txt";

            // Compiled Regular Expressions
            Regex metaTags = new Regex(@"<meta(.*?)>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            Regex anchorTags = new Regex(@"<a(.*?)>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

            // Get Webpage entered on command tail
            using (WebClient wc = new WebClient())
            {
                try
                {
                    Byte[] pageData = wc.DownloadData(@"http://" + args[0]);
                    pageHTML = Encoding.ASCII.GetString(pageData);
                }
                catch (WebException e)
                {
                    Console.WriteLine("WebClient Exception: {0}", e.Message);
                    System.Environment.Exit(-1);
                }
            }

            // Write results to text file
            using (FileStream fs = new FileStream(outputfileName, FileMode.Append, FileAccess.Write, FileShare.None))
            using (TextWriter writer = new StreamWriter(fs))
            {
                writer.WriteLine("\n----------------------- Start: {0} ------------------------------", args[0]);

                foreach (Match m in Regex.Matches(pageHTML, @"<title>(.*?)</title>", RegexOptions.IgnoreCase))
                {
                    writer.WriteLine(m.Value);
                    titleTagCount++;
                }

                writer.WriteLine("\n------------------------ Meta Tags -----------------------------------", args[0]);

                foreach (Match m in metaTags.Matches(pageHTML))
                {
                    writer.WriteLine(m.Value);
                    metaTagCount++;
                }

                writer.WriteLine("\n----------------------- Anchor Tags ----------------------------------", args[0]);
                foreach (Match m in anchorTags.Matches(pageHTML))
                {
                    writer.WriteLine(m.Value);
                    anchorTagCount++;
                }

                writer.WriteLine("\n--------------------------- Summary ----------------------------------", args[0]);
                writer.WriteLine("Title  Tag Count: {0}", titleTagCount);
                writer.WriteLine("Meta   Tag Count: {0}", metaTagCount);
                writer.WriteLine("Anchor Tag Count: {0}", anchorTagCount);
                // Format and display run time.
                stopWatch1.Stop();
                TimeSpan ts = stopWatch1.Elapsed;
                string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                    ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
                writer.WriteLine("Program Run Time: {0}", elapsedTime);
                writer.WriteLine("Program Run Date: {0}", currentTimestamp);
                writer.WriteLine("\n------------------------ End: {0} ---------------------------------", args[0]);
            }

            // Write finished message
            Console.WriteLine("\nResults saved in: {0}\n", outputfileName);
        }
    }
}

Top



Reference Articles

Top