每次迭代后更新帧
Update frame after each iteration
我目前正在为 Mac 在 Qt(C++) 中编写一个端口扫描器。检查某个端口是否打开的过程完全正常。 但是如果用户要检查的端口范围太大,每个端口都会检查,但只有在这个过程之后才会输出。
该程序实际上应该检查例如端口 1 并输出结果。之后它应该检查下一个和输出等等...
void MainWindow::checkPort(int portmin, int portmax, string ip) {
int dif = portmax - portmin;
if (dif <= 0)
return;
unsigned int open = 0;
unsigned int closed = 0;
int checked = 0;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
for (int i = portmin; i <= portmax; i++) {
int s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
int con = ::connect(s, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr));
if (con == 0){
ui->textEdit->setTextColor(Qt::green);
ui->textEdit->append("Port " + QString::number(i) + " open.");
open++;
}
if (con == -1) {
ui->textEdit->setTextColor(Qt::red);
ui->textEdit->append("Port " + QString::number(i) + " closed.");
closed++;
}
::close(con);
::close(s);
checked++;
}
您是否建议我如何在每次迭代后得到一个输出?
也许是这样的:
//...
bool tooManyPorts = dif > 10000; // Set flag to true if port range is too big (for example more than 10 000 ports
//
QString msgs = "";
for (int i = portmin; i <= portmax; i++) {
int s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
if (con == 0){
if (tooManyPorts) {
QString("<font color='green'>Port " + QString::number(i) + " open.</font><br/>");
}
else {
ui->textEdit->setTextColor(Qt::green);
ui->textEdit->append("Port " + QString::number(i) + " open.");
}
open++;
}
if (con == -1) {
if (tooManyPorts) {
msgs += QString("<font color='red'>Port " + QString::number(i) + " closed.</font><br/>");
}
else {
ui->textEdit->setTextColor(Qt::red);
ui->textEdit->append("Port " + QString::number(i) + " closed.");
}
closed++;
}
// ...
}
if(tooManyPorts) {
ui->textEdit->append(msgs); // Add all iteration messages to text edit
}
请注意 HTML 格式部分的用法。
这会在循环后将所有输出添加到您的字段中。要让它在每次迭代中都起作用,只需在循环中设置 msgs = ...
而不是 msgs += ...
,然后将 if(tooManyPorts) ...
移动到 for
的末尾,但不要移到外面。坦率地说,我很难理解您是否不想要第一个版本(在循环之后),因为现在您 在每个迭代步骤中将输出添加到文本字段。
最简单的解决方案是 运行 整个扫描作业并发使用线程池。线程间通信通过信号槽机制安全完成:
// https://github.com/KubaO/Whosebugn/tree/master/questions/async-portscan-39469180
#include <QtWidgets>
#include <QtConcurrent>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
class Scanner : public QObject {
Q_OBJECT
bool running = false, stop = false;
int open = 0, closed = 0, total = 0;
void scan() {
running = true;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
for (int i = 1; i < 65536 && !stop; ++i) {
auto s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
auto con = ::connect(s, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr));
emit hasResult(i, con == 0);
con == 0 ? ++open : ++closed;
++total;
::close(s);
}
emit done();
running = false;
}
public:
~Scanner() {
stop = true;
while (running);
}
Q_SIGNAL void hasResult(int port, bool open);
Q_SIGNAL void done();
Q_SLOT void start() {
QtConcurrent::run(this, &Scanner::scan);
}
};
int main(int argc, char ** argv) {
using Q = QObject;
QApplication app{argc, argv};
QWidget ui;
QVBoxLayout layout{&ui};
QTextBrowser log;
QProgressBar bar;
QPushButton scan{"Scan localhost"};
layout.addWidget(&log);
layout.addWidget(&bar);
layout.addWidget(&scan);
bar.setRange(1, 65535);
ui.show();
Scanner scanner;
Q::connect(&scan, &QPushButton::clicked, &scanner, [&]{
scan.setEnabled(false);
scanner.start();
});
Q::connect(&scanner, &Scanner::hasResult, &log, [&](int port, bool isOpen){
bar.setValue(port);
if (!isOpen) return;
auto color = isOpen ? QStringLiteral("green") : QStringLiteral("red");
auto state = isOpen ? QStringLiteral("open") : QStringLiteral("closed");
log.append(QStringLiteral("<font color=\"%1\">Port %2 is %3.</font><br/>").
arg(color).arg(port).arg(state));
});
Q::connect(&scanner, &Scanner::done, &scan, [&]{
bar.reset();
scan.setEnabled(true);
});
return app.exec();
}
#include "main.moc"
我目前正在为 Mac 在 Qt(C++) 中编写一个端口扫描器。检查某个端口是否打开的过程完全正常。 但是如果用户要检查的端口范围太大,每个端口都会检查,但只有在这个过程之后才会输出。 该程序实际上应该检查例如端口 1 并输出结果。之后它应该检查下一个和输出等等...
void MainWindow::checkPort(int portmin, int portmax, string ip) {
int dif = portmax - portmin;
if (dif <= 0)
return;
unsigned int open = 0;
unsigned int closed = 0;
int checked = 0;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
for (int i = portmin; i <= portmax; i++) {
int s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
int con = ::connect(s, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr));
if (con == 0){
ui->textEdit->setTextColor(Qt::green);
ui->textEdit->append("Port " + QString::number(i) + " open.");
open++;
}
if (con == -1) {
ui->textEdit->setTextColor(Qt::red);
ui->textEdit->append("Port " + QString::number(i) + " closed.");
closed++;
}
::close(con);
::close(s);
checked++;
}
您是否建议我如何在每次迭代后得到一个输出?
也许是这样的:
//...
bool tooManyPorts = dif > 10000; // Set flag to true if port range is too big (for example more than 10 000 ports
//
QString msgs = "";
for (int i = portmin; i <= portmax; i++) {
int s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
if (con == 0){
if (tooManyPorts) {
QString("<font color='green'>Port " + QString::number(i) + " open.</font><br/>");
}
else {
ui->textEdit->setTextColor(Qt::green);
ui->textEdit->append("Port " + QString::number(i) + " open.");
}
open++;
}
if (con == -1) {
if (tooManyPorts) {
msgs += QString("<font color='red'>Port " + QString::number(i) + " closed.</font><br/>");
}
else {
ui->textEdit->setTextColor(Qt::red);
ui->textEdit->append("Port " + QString::number(i) + " closed.");
}
closed++;
}
// ...
}
if(tooManyPorts) {
ui->textEdit->append(msgs); // Add all iteration messages to text edit
}
请注意 HTML 格式部分的用法。
这会在循环后将所有输出添加到您的字段中。要让它在每次迭代中都起作用,只需在循环中设置 msgs = ...
而不是 msgs += ...
,然后将 if(tooManyPorts) ...
移动到 for
的末尾,但不要移到外面。坦率地说,我很难理解您是否不想要第一个版本(在循环之后),因为现在您 在每个迭代步骤中将输出添加到文本字段。
最简单的解决方案是 运行 整个扫描作业并发使用线程池。线程间通信通过信号槽机制安全完成:
// https://github.com/KubaO/Whosebugn/tree/master/questions/async-portscan-39469180
#include <QtWidgets>
#include <QtConcurrent>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
class Scanner : public QObject {
Q_OBJECT
bool running = false, stop = false;
int open = 0, closed = 0, total = 0;
void scan() {
running = true;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
for (int i = 1; i < 65536 && !stop; ++i) {
auto s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
auto con = ::connect(s, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr));
emit hasResult(i, con == 0);
con == 0 ? ++open : ++closed;
++total;
::close(s);
}
emit done();
running = false;
}
public:
~Scanner() {
stop = true;
while (running);
}
Q_SIGNAL void hasResult(int port, bool open);
Q_SIGNAL void done();
Q_SLOT void start() {
QtConcurrent::run(this, &Scanner::scan);
}
};
int main(int argc, char ** argv) {
using Q = QObject;
QApplication app{argc, argv};
QWidget ui;
QVBoxLayout layout{&ui};
QTextBrowser log;
QProgressBar bar;
QPushButton scan{"Scan localhost"};
layout.addWidget(&log);
layout.addWidget(&bar);
layout.addWidget(&scan);
bar.setRange(1, 65535);
ui.show();
Scanner scanner;
Q::connect(&scan, &QPushButton::clicked, &scanner, [&]{
scan.setEnabled(false);
scanner.start();
});
Q::connect(&scanner, &Scanner::hasResult, &log, [&](int port, bool isOpen){
bar.setValue(port);
if (!isOpen) return;
auto color = isOpen ? QStringLiteral("green") : QStringLiteral("red");
auto state = isOpen ? QStringLiteral("open") : QStringLiteral("closed");
log.append(QStringLiteral("<font color=\"%1\">Port %2 is %3.</font><br/>").
arg(color).arg(port).arg(state));
});
Q::connect(&scanner, &Scanner::done, &scan, [&]{
bar.reset();
scan.setEnabled(true);
});
return app.exec();
}
#include "main.moc"