一个端口扫描程序就是对一段区域内的端口进行连接测试,如果能够连接上则标识这个端口是开放的。为了简化程序,我只是TCP连接方式的 端口进行扫描。为了加快扫描速度,我需要使用多线程,用ThreadPool对线程进行维护。
首先,定义一个端口扫描的类,该类实现对指定地址、指定端口进行扫描,并将扫描的结果(能、不能连接)保存 ,代码如下:(注意,为了加快端口扫描的速度,我对 Socket 的Connect采用异步方式,而信号灯等待1秒仍然没有得到结果,就认为没有连接到对方主机)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace PortScaner
{
public class PortScaner
{
private ManualResetEvent manualEvent;
private string hostName;
private bool connected;
private int port;
public bool Connected {
get { return connected; }
}
public string HostName {
get { return hostName; }
set { hostName = value; }
}
public int Port {
get { return port; }
set { port = value; }
}
public PortScaner(string hostName, int port) {
this.hostName = hostName;
this.port = port;
this.connected = false;
manualEvent = new ManualResetEvent(false);
}
/// <summary>
/// 扫描指定主机的指定端口
/// </summary>
/// <returns></returns>
public void Scan( ) {
Socket s = null;
manualEvent.Reset();
try {
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.BeginConnect(this.hostName, this.port, new AsyncCallback(EndConnected), s);
if (manualEvent.WaitOne(1000, false) == true) {
connected = s.Connected;
}
else {
connected = false;
}
}
catch (Exception ) {
connected = false;
}
finally {
if (s != null) {
s.Close();
s = null;
}
}
}
public void EndConnected(IAsyncResult ar) {
try {
Socket sk = (Socket)ar.AsyncState;
sk.EndConnect(ar);
}
catch (Exception) {
connected = false;
}
finally {
manualEvent.Set();
}
}
}
}
接下来就是,在多线程的环境中执行Scan了,代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace PortScaner
{
public class MyThreadState
{
private PortScaner portScaner;
private AutoResetEvent autoEvent;
public PortScaner PortScaner {
get { return portScaner; }
set { portScaner = value; }
}
public AutoResetEvent AutoEvent {
get { return autoEvent; }
set { autoEvent = value; }
}
public MyThreadState(PortScaner portScaner, AutoResetEvent autoEvent) {
this.portScaner = portScaner;
this.autoEvent = autoEvent;
}
}
public class PortScanerManager
{
private string hostName;
private int startPort;
private int endPort;
private int maxThread;
#region 属性和构造函数
public string HostName {
get { return hostName; }
set { hostName = value; }
}
public int StartPort {
get { return startPort; }
set { startPort = value; }
}
public int EndPort {
get { return endPort; }
set { endPort = value; }
}
public int MaxThread {
get { return maxThread; }
set {
if (value > 25)
maxThread = 25;
else
maxThread = value;
}
}
public PortScanerManager(string hostName) {
this.hostName = hostName;
this.startPort = 100;
this.endPort = 2000;
this.maxThread = 25;
}
public PortScanerManager(string hostName, int startPort, int endPort) {
this.hostName = hostName;
this.startPort = startPort;
this.endPort = endPort;
this.maxThread = 25;
}
#endregion
public List<int> Start() {
List<PortScaner > scaners = new List<PortScaner >();
WaitCallback callBack = new WaitCallback(ThreadWork);
if (maxThread > endPort - startPort) {
maxThread = endPort - startPort;
}
ThreadPool.SetMaxThreads(maxThread, maxThread + 10);
int runingThread = 0;
int curPort = startPort;
while (runingThread < endPort - startPort) {
int needThread = (endPort - curPort) > maxThread ? maxThread : (endPort - curPort);
AutoResetEvent[] autoEvents = new AutoResetEvent[needThread];
for (int i = 0; i < needThread; i++) {
PortScaner scaner = new PortScaner(this.hostName, curPort);
scaners.Add(scaner);
autoEvents[i] = new AutoResetEvent(false);
MyThreadState state = new MyThreadState(scaner, autoEvents[i]);
ThreadPool.QueueUserWorkItem(callBack, state);
curPort++;
runingThread++;
}
WaitHandle.WaitAll (autoEvents);
}
List<int> result = new List<int> ();
for (int i = 0; i < scaners.Count; i++) {
if (scaners[i].Connected == true)
result.Add(scaners[i].Port);
}
return result;
}
private void ThreadWork(object state) {
((MyThreadState )state).PortScaner .Scan();
((MyThreadState)state).AutoEvent.Set();
}
}
}
呵呵,这里用了比较 bt 的办法, WaitHandle.WaitAll (autoEvents);这是为了前面讲的原理写的,而为了不那么bt可以采用推拉窗技术。
好了,就说了这么多,一则希望能对大家有所帮助,二则希望自己将来写程序的时候,能够很快的进入状态。