- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已修改 ICMP ping 实现 (https://think-async.com/Asio/asio-1.18.0/src/examples/cpp03/icmp/ping.cpp) 以同时 ping 多个目标,而不是如示例中所示的顺序。我尝试使用 std::thread 和 std::async(以及 future )。
但只有当所有目的地都无法到达时,它才能按预期工作。不能同时进行吗?我在 pinger 类中禁用了对结果/超时的重新 ping
const char* ping(const char* destination)
{
asio::io_context io_context;
pinger p(io_context, destination);
io_context.run();
return p.get();
}
int main()
{
std::future<const char*> a1 = std::async(std::launch::async, ping, "10.2.7.196");
std::future<const char*> a2 = std::async(std::launch::async, ping, "10.2.7.19");
std::cout<<a1.get()<<std::endl;
std::cout<<a2.get()<<std::endl;
}
最佳答案
你不需要std::async
¹。
但是从你展示的一小段代码我可以猜测 ² 您的错误返回原始 char const*
.他们引用 pinger
中的数据的可能性很大。这 - 显然 - 在 future 完成时不再有效(pinger
将超出范围)。
发生这种情况的典型方法是将输出存储在 std::string
中。成员并从 get()
返回使用 .c_str()
.
A reason why it would "work" for unreachable targets would be if
get()
simply returned a string literal likereturn "unreachable"
, which would NOT have the lifetime problem described above.
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
namespace asio = boost::asio;
#include "icmp_header.hpp"
#include "ipv4_header.hpp"
using asio::steady_timer;
using asio::ip::icmp;
namespace chrono = asio::chrono;
class pinger {
public:
pinger(asio::io_context& io_context, const char* destination)
: resolver_(io_context), socket_(io_context, icmp::v4()),
timer_(io_context), sequence_number_(0), num_replies_(0) {
destination_ = *resolver_.resolve(icmp::v4(), destination, "").begin();
start_send();
start_receive();
}
std::string get() { auto r = _output.str(); _output.str(""); return r; }
private:
void start_send() {
std::string body("\"Hello!\" from Asio ping.");
// Create an ICMP header for an echo request.
icmp_header echo_request;
echo_request.type(icmp_header::echo_request);
echo_request.code(0);
echo_request.identifier(get_identifier());
echo_request.sequence_number(++sequence_number_);
compute_checksum(echo_request, body.begin(), body.end());
// Encode the request packet.
asio::streambuf request_buffer;
std::ostream os(&request_buffer);
os << echo_request << body;
// Send the request.
time_sent_ = steady_timer::clock_type::now();
socket_.send_to(request_buffer.data(), destination_);
// Wait up to five seconds for a reply.
num_replies_ = 0;
timer_.expires_at(time_sent_ + chrono::seconds(5));
timer_.async_wait(boost::bind(&pinger::handle_timeout, this));
}
void handle_timeout() {
if (num_replies_ == 0)
_output << "Request timed out";
//// Requests must be sent no less than one second apart.
//timer_.expires_at(time_sent_ + chrono::seconds(1));
//timer_.async_wait(boost::bind(&pinger::start_send, this));
}
void start_receive() {
// Discard any data already in the buffer.
reply_buffer_.consume(reply_buffer_.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
socket_.async_receive(reply_buffer_.prepare(65536),
boost::bind(&pinger::handle_receive, this,
boost::placeholders::_2));
}
void handle_receive(std::size_t length) {
// The actual number of bytes received is committed to the buffer so
// that we can extract it using a std::istream object.
reply_buffer_.commit(length);
// Decode the reply packet.
std::istream is(&reply_buffer_);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter out only the echo replies that match the our identifier and
// expected sequence number.
if (is && icmp_hdr.type() == icmp_header::echo_reply &&
icmp_hdr.identifier() == get_identifier() &&
icmp_hdr.sequence_number() == sequence_number_) {
// If this is the first reply, interrupt the five second timeout.
if (num_replies_++ == 0)
timer_.cancel();
// Print out some information about the reply packet.
chrono::steady_clock::time_point now = chrono::steady_clock::now();
chrono::steady_clock::duration elapsed = now - time_sent_;
_output
<< length - ipv4_hdr.header_length() << " bytes from "
<< ipv4_hdr.source_address()
<< ": icmp_seq=" << icmp_hdr.sequence_number()
<< ", ttl=" << ipv4_hdr.time_to_live() << ", time="
<< chrono::duration_cast<chrono::milliseconds>(elapsed).count();
}
//start_receive();
}
static unsigned short get_identifier() {
#if defined(ASIO_WINDOWS)
return static_cast<unsigned short>(::GetCurrentProcessId());
#else
return static_cast<unsigned short>(::getpid());
#endif
}
std::ostringstream _output;
icmp::resolver resolver_;
icmp::endpoint destination_;
icmp::socket socket_;
steady_timer timer_;
unsigned short sequence_number_;
chrono::steady_clock::time_point time_sent_;
asio::streambuf reply_buffer_;
std::size_t num_replies_;
};
std::string ping1(const char* destination) {
asio::io_context io_context;
pinger p(io_context, destination);
io_context.run();
return p.get();
}
#include <list>
#include <iostream>
int main(int argc, char** argv) {
std::list<std::future<std::string> > futures;
for (char const* arg : std::vector(argv+1, argv+argc)) {
futures.push_back(std::async(std::launch::async, ping1, arg));
}
for (auto& f : futures) {
std::cout << f.get() << std::endl;
}
}
如您所见,我制作了目的地命令行参数列表。因此,当我像这样运行它时:
sudo ./sotest 127.0.0.{1..100} |& sort | uniq -c
我得到这个输出:
1 32 bytes from 127.0.0.12: icmp_seq=1, ttl=64, time=0
1 32 bytes from 127.0.0.16: icmp_seq=1, ttl=64, time=0
7 32 bytes from 127.0.0.44: icmp_seq=1, ttl=64, time=0
1 32 bytes from 127.0.0.77: icmp_seq=1, ttl=64, time=1
1 32 bytes from 127.0.0.82: icmp_seq=1, ttl=64, time=1
1 32 bytes from 127.0.0.9: icmp_seq=1, ttl=64, time=0
88 Request timed out
I'm not actually sure why so many time out, but the point is correct code now. This code runs and completes UBSan/ASan clean. See below for the fix discovered later, though
io_service
每平。让我们在一个人身上完成这一切。
#include <list>
#include <iostream>
int main(int argc, char** argv) {
asio::io_context io_context;
std::list<pinger> pingers;
for (char const* arg : std::vector(argv+1, argv+argc)) {
pingers.emplace_back(io_context, arg);
}
io_context.run();
for (auto& p : pingers) {
std::cout << p.get() << std::endl;
}
}
注意这里的同步点是
io_context.run()
,就像以前一样,除了现在它在主线程上一次性运行所有 ping。
handle_receive
需要过滤掉不响应我们 ping 的 ICMP 回复,所以如果发生这种情况,我们需要继续
start_receive()
直到我们得到它:
void start_receive() {
// Discard any data already in the buffer.
reply_buffer_.consume(reply_buffer_.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
socket_.async_receive(reply_buffer_.prepare(65536),
boost::bind(&pinger::handle_receive, this,
boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
}
void handle_receive(boost::system::error_code ec, std::size_t length) {
if (ec) {
if (ec == boost::asio::error::operation_aborted) {
_output << "Request timed out";
} else {
_output << "error: " << ec.message();
}
return;
}
// The actual number of bytes received is committed to the buffer so
// that we can extract it using a std::istream object.
reply_buffer_.commit(length);
// Decode the reply packet.
std::istream is(&reply_buffer_);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter out only the echo replies that match the our identifier and
// expected sequence number.
if (is && icmp_hdr.type() == icmp_header::echo_reply &&
icmp_hdr.identifier() == get_identifier() &&
icmp_hdr.sequence_number() == sequence_number_) {
// If this is the first reply, interrupt the five second timeout.
if (num_replies_++ == 0)
timer_.cancel();
// Print out some information about the reply packet.
chrono::steady_clock::time_point now = chrono::steady_clock::now();
chrono::steady_clock::duration elapsed = now - time_sent_;
_output
<< length - ipv4_hdr.header_length() << " bytes from "
<< ipv4_hdr.source_address()
<< ": icmp_seq=" << icmp_hdr.sequence_number()
<< ", ttl=" << ipv4_hdr.time_to_live() << ", time="
<< chrono::duration_cast<chrono::milliseconds>(elapsed).count();
} else start_receive();
}
现在,
handle_timeout
可以简化为:
void handle_timeout() {
if (num_replies_ == 0) {
socket_.cancel(); // _output is set in response to error_code
}
}
In fact, we might simplify to remove
num_replies
altogether, but I'll leave this as an exorcism for the reader
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
namespace asio = boost::asio;
#include "icmp_header.hpp"
#include "ipv4_header.hpp"
using asio::steady_timer;
using asio::ip::icmp;
namespace chrono = asio::chrono;
class pinger {
public:
pinger(asio::io_context& io_context, const char* destination)
: resolver_(io_context), socket_(io_context, icmp::v4()),
timer_(io_context), sequence_number_(0), num_replies_(0) {
destination_ = *resolver_.resolve(icmp::v4(), destination, "").begin();
start_send();
start_receive();
}
std::string get() { auto r = _output.str(); _output.str(""); return r; }
private:
void start_send() {
std::string body("\"Hello!\" from Asio ping.");
// Create an ICMP header for an echo request.
icmp_header echo_request;
echo_request.type(icmp_header::echo_request);
echo_request.code(0);
echo_request.identifier(get_identifier());
echo_request.sequence_number(++sequence_number_);
compute_checksum(echo_request, body.begin(), body.end());
// Encode the request packet.
asio::streambuf request_buffer;
std::ostream os(&request_buffer);
os << echo_request << body;
// Send the request.
time_sent_ = steady_timer::clock_type::now();
socket_.send_to(request_buffer.data(), destination_);
// Wait up to five seconds for a reply.
num_replies_ = 0;
timer_.expires_at(time_sent_ + chrono::seconds(5));
timer_.async_wait(boost::bind(&pinger::handle_timeout, this));
}
void handle_timeout() {
if (num_replies_ == 0) {
socket_.cancel(); // _output is set in response to error_code
}
}
void start_receive() {
// Discard any data already in the buffer.
reply_buffer_.consume(reply_buffer_.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
socket_.async_receive(reply_buffer_.prepare(65536),
boost::bind(&pinger::handle_receive, this,
boost::asio::placeholders::error(),
boost::asio::placeholders::bytes_transferred()));
}
void handle_receive(boost::system::error_code ec, std::size_t length) {
if (ec) {
if (ec == boost::asio::error::operation_aborted) {
_output << "Request timed out";
} else {
_output << "error: " << ec.message();
}
return;
}
// The actual number of bytes received is committed to the buffer so
// that we can extract it using a std::istream object.
reply_buffer_.commit(length);
// Decode the reply packet.
std::istream is(&reply_buffer_);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter out only the echo replies that match the our identifier and
// expected sequence number.
if (is && icmp_hdr.type() == icmp_header::echo_reply &&
icmp_hdr.identifier() == get_identifier() &&
icmp_hdr.sequence_number() == sequence_number_) {
// If this is the first reply, interrupt the five second timeout.
if (num_replies_++ == 0)
timer_.cancel();
// Print out some information about the reply packet.
chrono::steady_clock::time_point now = chrono::steady_clock::now();
chrono::steady_clock::duration elapsed = now - time_sent_;
_output
<< length - ipv4_hdr.header_length() << " bytes from "
<< ipv4_hdr.source_address()
<< ": icmp_seq=" << icmp_hdr.sequence_number()
<< ", ttl=" << ipv4_hdr.time_to_live() << ", time="
<< chrono::duration_cast<chrono::milliseconds>(elapsed).count();
} else start_receive();
}
static unsigned short get_identifier() {
#if defined(ASIO_WINDOWS)
return static_cast<unsigned short>(::GetCurrentProcessId());
#else
return static_cast<unsigned short>(::getpid());
#endif
}
std::ostringstream _output;
icmp::resolver resolver_;
icmp::endpoint destination_;
icmp::socket socket_;
steady_timer timer_;
unsigned short sequence_number_;
chrono::steady_clock::time_point time_sent_;
asio::streambuf reply_buffer_;
std::size_t num_replies_;
};
#include <list>
#include <iostream>
int main(int argc, char** argv) {
asio::io_context io_context;
std::list<pinger> pingers;
for (char const* arg : std::vector(argv+1, argv+argc)) {
pingers.emplace_back(io_context, arg);
}
io_context.run();
for (auto& p : pingers) {
std::cout << p.get() << std::endl;
}
}
现在例如的输出
time sudo ./sotest 127.0.0.{1..100} 18.0.0.1
正如预期的那样:
32 bytes from 127.0.0.1: icmp_seq=1, ttl=64, time=8
32 bytes from 127.0.0.2: icmp_seq=1, ttl=64, time=8
32 bytes from 127.0.0.3: icmp_seq=1, ttl=64, time=8
32 bytes from 127.0.0.4: icmp_seq=1, ttl=64, time=8
...
32 bytes from 127.0.0.98: icmp_seq=1, ttl=64, time=0
32 bytes from 127.0.0.99: icmp_seq=1, ttl=64, time=0
32 bytes from 127.0.0.100: icmp_seq=1, ttl=64, time=0
Request timed out
关于c++ - 使用 Boost.asio 并行 Ping(ICMP) 多个目的地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63470803/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!