Blue Theme Orange Theme Green Theme Red Theme
 
HeaderAd
Home | Forums | Videos | Photos | Blogs | E-Books | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
New MS SQL 2008 Available - DiscountASP.NET
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » Threading » Multi-threaded Web Applications - Case II: Port Scanner

Multi-threaded Web Applications - Case II: Port Scanner

This article continues the 4-parts series of Multi-threaded Web Applications. In the first part, I have demonstrated how you can use multi-threading with ASP.NET to make a web based search engine more responsive, and to reduce the time required to compose the result. In this article, I will demonstrate how you can apply the same technique to a web based port scanner.

Technologies: .NET 1.0/1.1,Visual C# .NET
Total downloads : 200
Total page views :  9888
Rating :
 5/5
This article has been rated :  1 times
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
MultiThreadedPortScanner.zip
 
ArticleAd
Become a Sponsor



Overview

This article continues the 4-parts series of Multi-threaded Web Applications. In the first part, I have demonstrated how you can use multi-threading with ASP.NET to make a web based search engine more responsive, and to reduce the time required to compose the result. In this article, I will demonstrate how you can apply the same technique to a web based port scanner.

Description

This articles assume some basic understanding of multi-threading in .NET. You can refer back to the first part for more information on it at:

http://www.c-sharpcorner.com/UploadFile/tinlam/MultithreadedWebApplications11172005002508AM/
MultithreadedWebApplications.aspx?ArticleID=fbdb99db-ef57-47b7-bba6-7ab9bd6a1001
.

The function of the port scanner we will be seeing shortly is simple. It determines rather a given port on a given IP address is open or closed, by initiating a connection to it. If a connection to the port can be made successfully, then its open. But if the connection to the port is rejected, unreachable, or timed out, then its closed. With some additional logic to parse the IP/host names and the ports, the logic of the port scanner is almost identical to the search engine in Part I. The port scanner will create a thread for each port and IP/host. Then each thread will be started, and connect to their assigned port and IP independently from all the rest. When all the threads are started, then the port scanner will wait for all of them to return.

The port scanner consists of only 2 files. (1) portscanner.aspx, which contains the form for entering the ip/hosts and ports, and a repeater control to display the result. And depending on the state of the page, one of the other will be hidden while the other one is displayed. (2) portscanner.aspx.cs, which is the code-behind file behind portscanner.aspx. It contains the classes and methods that perform the port scanning logic. Both files were developed and tested in the VS.NET (RTM edition), and the final edition of the .NET Framework SDK.

Lets look at the portscanner.aspx first:

<%@ Page Language="C#" AutoEventWireUp="false"
Inherits="MultiThreadedWebApp.PortScanner" Src="portscanner.aspx.cs" %>
<script language="c#" runat="server">
protected void scan(Object sender, EventArgs e) {
if ( Scan( urls.Text ) ) {
info.Text = "Scan result:";
ScanForm.Visible = false;
ResultList.DataSource = ScanResults;
ResultList.DataBind();
}
}
</script>
<
html>
<
head>
<
title>Multi-threaded Port Scanner</title>
<
style>.BodyText { font-family: verdana; font-size: 12px; color: 333333; } </style>
</
head>
<
body>
<
asp:label id="info" class="BodyText" text="ip/host to scan, one url per entry."
runat="server" /><br />
<
asp:Repeater id="ResultList" runat="server">
<
HeaderTemplate>
<
table class="BodyText" border="0" cellpadding="3" cellspacing="3">
<
tr>
<
td><b>Status</b></td>
<
td><b>IP</b></td>
<
td><b>Port</b></td>
<
td><b>Responsed / Timed out</b></td>
</
tr>
</
HeaderTemplate>
<
ItemTemplate>
<
tr>
<
td><%# DataBinder.Eval(Container.DataItem, "status") %></td>
<
td><%# DataBinder.Eval(Container.DataItem, "ip") %></td>
<
td><%# DataBinder.Eval(Container.DataItem, "port") %></td>
<
td><%# DataBinder.Eval(Container.DataItem, "timeSpent") %></td>
</
tr>
</
ItemTemplate>
<
FooterTemplate>
</
table>
</
FooterTemplate>
</
asp:Repeater>
<
form id="ScanForm" runat = "server" >
<
table class="BodyText">
<
tr>
<
td valign="top">urls:</td>
<
td><asp:textbox class="BodyText" text="" id="urls" rows="10" columns="50" textmode="MultiLine" runat="server" /></td>
</
tr>
<
tr><td align="right" colspan="2">
<
asp:button class="BodyText" text="scan!" type="submit" onclick="scan" runat="server" ID="Button1"/>
</
td></tr>
</
table>
</
form>
</
body>
</
html>

Its pretty simple. The C# code block contains the method Scan(), which will be called when the user click the scan button. Theres a repeater control, which we will be binding scan result data to. Then theres a form, which we will be using to enter ip/host and port information. It will be hidden by the Scan() method, when we display the scan result via the repeater control.

Now comes some fancy stuff:

using System;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
namespace MultiThreadedWebApp
{
/// <summary>
/// this class inherits from the Page class.
/// the portscanner.aspx diverts from this class.
/// </summary>
public class PortScanner : System.Web.UI.Page
{
private string _ipPorts;
private ArrayList _ports;
/// <summary>
/// The ArrayList of ScanPort objects.
/// </summary>
public ArrayList ScanResults
{
get { return _ports; }
}
/// <summary>
/// This method is called to parse the string containing the ip and port information.
/// and creates An ArrayList of ScanPort objects.
/// </summary>
/// <param name="ipPorts">the string containing the ip and port information</param>
public void parse(string ipPorts)
{
string lPort = "";
string lIP = "";
int[] lPorts;
string[] lPortRange;
string[] lIPs = ipPorts.Split('\n');
int ipIdx, portRangeIdx, portIdx;
_ports =
new ArrayList();
// each ip/host, ex: www.microsoft.com:10-20,21,25,80,105-115
for ( ipIdx = 0; ipIdx < lIPs.Length; ipIdx ++ )
{
string[] ipInfo = lIPs[ipIdx].Split(':');
lIP = ipInfo[0];
lPortRange = ipInfo[1].Split(',');
// each port range, ex: 10-20,21,25,80,105-115
for ( portRangeIdx = 0; portRangeIdx < lPortRange.Length; portRangeIdx ++ )
{
// ex: 10-20
if ( lPortRange[portRangeIdx].IndexOf("-") != -1 )
{
string[] lBounds = lPortRange[portRangeIdx].Split('-');
int lStart = int.Parse( lBounds[0] );
int lEnd = int.Parse( lBounds[1] );
lPorts =
new int[ lEnd - lStart + 1] ;
int lIdx = 0;
for ( portIdx = lStart; portIdx <= lEnd; portIdx ++ )
lPorts[lIdx++] = portIdx;
}
else // ex: 80
lPorts = new int[] { int.Parse( lPortRange[portRangeIdx] ) };
// create a ScanPort object for each port,
// then add the object to the _ports ArrayList
for ( int lIdx = 0; lIdx < lPorts.Length; lIdx ++ )
_ports.Add(
new ScanPort( lIP, lPorts[lIdx] ) );
}
}
}
/// <summary>
/// This method creates, starts and manages the threads
/// </summary>
/// <param name="pIPs">The string containing the ip and port information passed from the portscanner.aspx</param>
/// <returns></returns>
public bool Scan(string pIPs)
{
try
{
// parse the string to ips and ports
parse(pIPs);
// create the threads
Thread[] lThreads = new Thread[ _ports.Count ];
int lIdx = 0;
// add the ScanPort objects' scan method to the threads, then run them.
for ( lIdx = 0; lIdx < _ports.Count; lIdx ++ )
{
lThreads[lIdx] =
new Thread( new ThreadStart( ((ScanPort)_ports[lIdx]).Scan ) );
lThreads[lIdx].Start();
}
// wait for all of them to finish
for ( lIdx = 0; lIdx < lThreads.Length; lIdx ++ )
lThreads[lIdx].Join();
return true;
}
catch
{
return false;
}
}
}
/// <summary>
/// This class does the work of connecting to the port.
/// </summary>
public class ScanPort
{
private string _ip = "";
private int _port = 0;
private TimeSpan _timeSpent;
private string _status = "Not scanned";
public string ip
{
get { return _ip; }
}
public int port
{
get { return _port; }
}
public string status
{
get { return _status; }
}
public TimeSpan timeSpent
{
get { return _timeSpent; }
}
private ScanPort() {}
public ScanPort(string ip, int port)
{
_ip = ip;
_port = port;
}
/// <summary>
/// initiate a connection to the port.
/// </summary>
public void Scan()
{
TcpClient scanningIpPort =
new TcpClient();
DateTime lStarted = DateTime.Now;
try
{
scanningIpPort.Connect( _ip, _port );
scanningIpPort.Close();
_status = "Open";
}
catch
{
_status = "Closed";
}
_timeSpent = DateTime.Now.Subtract( lStarted );
}
}
}

This code-behind file contains the namespace MultiThreadedWebApp. And there are 2 classes in this namespace: (1) PortScanner, which inherits the System.Web.UI.Page class. Its also the page portscaner.aspx diverts from. (2) ScanPort, which contains information about a given port and ip, as well as performing the scanning task.

The PortScanner contains 2 methods: (1) parse(), it accepts a string we passed to the class from the form. It then parse the string, extracting the ip/host and port information and construct the private member field _ports holding an ArrayList of ScanPort objects. _ports is accessed by the public property ScanResults. Note that in order for this method to parse the string properly, the string must be entered in a recognizable format. The format is: <ip | host>:<a port number | starting port numberending port number[,]>. It starts with the ip address or the host, then a :, then a list of individual port number, or a range of port numbers. Port numbers are separated by ,. And each ip/host entry is separated by the new line character. So for example: www.yahoo.com:80,100-11-,443, will mean to scan the ports 80, 100 to 110 and 443 on the host www.yahoo.com. (2) Scan(), it accepts a string we obtained from the form in portscanner.aspx. It then pass the string to parse() to parse it, and construct the _ports object. Once the parse() has done its part, and we have the _ports object containing the ip/host and port information, we can start scanning them. The method loops through the _ports ArrayList, creates a thread for each ScanPort object. As soon as the thread is created, its started. When it started all the threads, it then waits for them to finish before it itself returns to its caller (the portscanner.aspx).

The ScanPort contains just one method, Scan(). Its where the actual scanning task is performed. It first creates an object of type TcpClient in the System.Net.Socket namespace. It then passes the ip/host and port information that we has extracted by the parse() method, to its Connect() method. If a connection is made, we close it immediately, and set its status to Open. However, due to god knows what reasons, if the connection cannot be made, then the status is set to Closed. Note that if the scanning ip/host has the port opened behind a firewall, and only accessible from within its internal LAN, then its still closed to our port scanner, and we still determine its closed.

Port Scanner in action

Fire up the form, and type in some host/URLs:

 

Sit back, relax and wait for a few seconds:

 

Conclusion

Imagine if the port scanner does not have the multi-threading capability, and you have to scan all the ports one by one. Depending on how fast it can response to you, and rather its open or close, or how you set the timeout on the connection, each one might take up to 20 seconds. If you just have 15 ports to scan, it might take up to 5 minutes! Imagine if you want to do a full scan (some 60,000 ports) on an IP However, as mentioned in the last part, starting and running too many threads (like around 60,000 ports for a full scan) is also not good. But this is where the thread pooling comes in. More information on thread pooling can be found in the MSDN Library at:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconthreadpooling.asp?frame=true

Source Code

Copy and paste your source code if its not big, otherwise leave it blank and discuss about code in the description.


Login to add your contents and source code to this article
 [Top] Rate this article
 About the author
 
Tin Lam
Tin Lam is currently working as an independent consultant in NYC. He is also a freelance technical writer for various web sites. He specializes in software and web development with Microsoft technologies, but also has extensive knowledge in the Java and WAP technologies
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Boost the performance of your .NET applications
“ANTS Profiler took us straight to the specific areas of our code which were the cause of our performance issues." Terry Phillips, Sr. Developer, Harley-Davidson Dealer Systems. Download your free trial of ANTS Profiler.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
 
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
MultiThreadedPortScanner.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
ArticleAd
Become a Sponsor
Latest Comments:
Subject Posted By Posted On
pIPs?ju3/14/2008
public bool Scan(string pIPs) { try { parse(pIPs); I cant seem to understand how the portscanner.aspx passes the ip and port as "pIPs". I can't find where pIPs is set to contain the information?
Reply | Email | Delete | Modify | 

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 1999 - 2009  Mindcracker LLC. All Rights Reserved