所以我试图用给定的IP地址扫描开放端口。 我找到了一些例子,但是如果我给出65535个任务,我会得到Out of Memory异常。 我虽然嗯,也许它很多。所以我尝试了2000 ..还是很多。一千? YES。
但显然问题在于'TaskCreationOptions.LongRunning'。如果我尝试TaskCreationOptions.None是everyhting但真的很慢!!就像我奶奶可以更快地扫描端口一样。
有趣的是,如果我调试(F5 - Visual studio),那么它可以工作,但如果我执行程序而不调试它不会。 所以我可以在几秒钟内扫描1000个端口,但是如何实现队列?
这是我的代码。 我尝试循环,执行完成等等。没有:(
任何帮助都是适当的,提前谢谢!
private void ScanPorts()
{
int startPort = 1000;
int endPoint = 65535;
myProgressBar.Value = 0;
myProgressBar.Step = 1;
myProgressBar.Maximum = endPoint - startPort + 1;
var scans = from i in Enumerable.Range(startPort, endPoint - startPort + 1)
select ScanSinglePortTask(i).ContinueWith(t => Response(t.Result), TaskScheduler.FromCurrentSynchronizationContext());
var tasks = scans.ToArray();
}
private Task<string> ScanSinglePortTask(int currPort)
{
return Task.Factory.StartNew(() =>
{
try
{
using (var tcpportScan = new TcpClient())
{
tcpportScan.SendTimeout = 10;
tcpportScan.Connect("127.0.0.1", (int)currPort);
}
return "IP: 127.0.0.1 - Port " + currPort + " open.\n";
}
catch (Exception)
{
return "IP: 127.0.0.1 - Port " + currPort + " closed.\n";
}
}, TaskCreationOptions.LongRunning);
}
private void Response(object message)
{
lblProgress.Text = ((string)message);
listBox1.Items.Add(((string)message));
listBox1.SelectedIndex = listBox1.Items.Count - 1;
myProgressBar.PerformStep();
}
修改
TEMP SOLUTION
所以我设法通过将我的平台目标从x86设置为x64来摆脱Out of Memory异常。
因此,x86具有2Gigs的VIRTUAL内存,而x64则超过6TB + VIRTUAL内存。
如果你问我这不是一个解决方案,而是一个临时问题。
新解决方案
x86和x64位兼容!
我实施的排队系统,这篇文章没有答案,所以我想我会为那些需要它的人分享我的解决方案。
基本上,此代码扫描任何给定IP地址的所有端口(同时1000个端口,因此1000个线程) 我可以在2分钟内扫描一个本地IP,一个互联网IP有点长,可能是5个。取决于你的CPU速度和互联网连接。
我为你们添加了一些评论:)
(请不要将此用于黑客目的xD 并投票如果您喜欢)
public partial class PortScanner : Form
{
private int totalScans = 0;
private IPAddress ipAddress;
public PortScanner()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
//Check for valid IP
if (IPAddress.TryParse(txtIP.Text, out ipAddress))
{
btnScan.Enabled = false;
btnScan.Text = "Scanning...";
//Stops GUI Freeze
MethodInvoker startScanning = new MethodInvoker(ScanPorts);
startScanning.BeginInvoke(null, null);
}
else
{
MessageBox.Show("Invalid IP");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void ScanPorts()
{
int startPort = 1;
int endPoint = 65535;
// n ports to scan!
int maxTheads = 1000;
//Set progressbar
myProgressBar.Value = 0;
myProgressBar.Step = 1;
myProgressBar.Maximum = endPoint - startPort + 1;
//Main task list (consist of multiple lists of 1000 tasks)
List<List<Task>> myTasks = new List<List<Task>>();
for (int i = startPort; i <= endPoint; i = i + maxTheads)
{
List<Task> subTasks = new List<Task>();
for (int j = i; j < i + maxTheads && j <= endPoint; j++)
{
subTasks.Add(ScanSinglePortTask(j));
}
myTasks.Add(subTasks);
}
//Start ALL TASKS
startTask(myTasks);
}
public void startTask(List<List<Task>> myTasks)
{
//A thousand task at a time.
foreach (List<Task> t in myTasks)
{
foreach (Task st in t)
{
st.Start();
}
Task.WaitAll(t.ToArray());
}
btnScan.Enabled = true;
btnScan.Text = "Start Scanning";
}
private Task ScanSinglePortTask(int currPort)
{
return new Task(()=>
{
try
{
using (var tcpportScan = new TcpClient())
{
tcpportScan.SendTimeout = 10;
tcpportScan.Connect(ipAddress, (int)currPort);
}
Response("IP: " + ipAddress.ToString() + " - Port " + currPort + " open.\n");
}
catch (Exception)
{
Response("IP: " + ipAddress.ToString() + " - Port " + currPort + " closed.\n");
}
}, TaskCreationOptions.LongRunning);
}
private void Response(object message)
{
totalScans++;
if (message != null)
{
try
{
lblProgress.Text = "Total portscan: " + totalScans.ToString();
lbConnections.Items.Add(((string)message));
lbConnections.SelectedIndex = lbConnections.Items.Count - 1;
myProgressBar.PerformStep();
if (((string)message).EndsWith("open.\n"))
{
lbOpenConnections.Items.Add((string)message);
}
}
catch (Exception)
{
}
}
}
}
答案 0 :(得分:0)
.Net中的每个托管线程或光纤都占用一兆字节的堆栈空间。如果你不需要那么多的堆栈空间并希望有更多的线程(顺便说一句,这并不是说这是一个好主意!)你可以控制堆栈空间大小,减少它应该允许创建更多的线程
本文将帮助您了解LongRunning为何会产生影响;你基本上绕过了线程池并创建了一个专用线程。