您的位置:首页 > 编程语言 > C#

c#的ThreadPool使用笔记(四)--实例:端口扫描程序

2009-06-08 20:55 513 查看
一个端口扫描程序就是对一段区域内的端口进行连接测试,如果能够连接上则标识这个端口是开放的。为了简化程序,我只是TCP连接方式的 端口进行扫描。为了加快扫描速度,我需要使用多线程,用ThreadPool对线程进行维护。

首先,定义一个端口扫描的类,该类实现对指定地址、指定端口进行扫描,并将扫描的结果(能、不能连接)保存 ,代码如下:(注意,为了加快端口扫描的速度,我对 Socket 的Connect采用异步方式,而信号灯等待1秒仍然没有得到结果,就认为没有连接到对方主机)

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可以采用推拉窗技术。

好了,就说了这么多,一则希望能对大家有所帮助,二则希望自己将来写程序的时候,能够很快的进入状态。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: