- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个使用 Boost ASIO 的 TCP 服务器。我注意到,在 Linux 上使用链接作用域的 IPv6 地址时,我无法在不引发异常的情况下创建 boost::asio::ip::tcp::acceptor
。使用全局 IPv6 地址或 IPv4 地址都可以正常工作。
我很确定问题出在范围 ID 设置不正确,但我不知道如何解决这个问题。
我正在使用 ubuntu 提供的 boost 1.40.0 库在 Ubuntu 11.04 LTS 上进行开发。这是我的服务器代码的一个非常简单的版本,它显示了问题:
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
/* To Compile:
g++ -Wall -o ./asio-ipv6 ./asio-ipv6.cpp -lboost_system
*/
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> TcpSocketPtr;
typedef boost::shared_ptr<boost::asio::ip::tcp::acceptor> TcpAcceptorPtr;
typedef boost::shared_ptr<boost::asio::ip::tcp::endpoint> TcpEndpointPtr;
class AsioServer{
public:
AsioServer(boost::asio::io_service& io): io_(io){};
//throws
void accept(const std::string& ipString,unsigned short port){
boost::asio::ip::address addr = boost::asio::ip::address::from_string(ipString);
std::cout << "Valid IP address " << ipString << std::endl;
this->endpoint_.reset(new boost::asio::ip::tcp::endpoint(addr,port));
std::cout << "Created endpoint" << std::endl;
//Will throw if a link local IPv6 address is used
acceptor_.reset(new boost::asio::ip::tcp::acceptor(this->io_,*(this->endpoint_)));
std::cout << "About to accept on " << *(this->endpoint_) << std::endl;
this->socket_.reset(new boost::asio::ip::tcp::socket(this->io_));
this->acceptor_->async_accept(*socket_ ,boost::bind(&AsioServer::handle_accept,this,boost::asio::placeholders::error));
}
private:
boost::asio::io_service& io_;
TcpSocketPtr socket_;
TcpAcceptorPtr acceptor_;
TcpEndpointPtr endpoint_;
void handle_accept(const boost::system::error_code &ec){
if(!ec){
std::cout << "Accepted connection!" << std::endl;
}
else{
std::cout << "Error accepting connection" << std::endl;
}
};
};
int main(int argc, char* argv[]){
boost::asio::io_service io;
std::string ipString("0.0.0.0");
if(argc > 1){
ipString.assign(argv[1]);
}
std::cout << "IP Set to " << ipString << std::endl;
AsioServer server(io);
try{
server.accept(ipString,4444);
}
catch(const std::exception& e){
std::cout << "Error caught: " << e.what() << std::endl;
}
io.run();
std::cout << "Done!" << std::endl;
return 0;
}
在这台机器上,我为 eth0 配置了以下内容:
$ ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0c:29:10:cf:0e
inet addr:192.168.97.162 Bcast:192.168.97.255 Mask:255.255.255.0
inet6 addr: 2620:1c:8000:190:20c:29ff:fe10:cf0e/64 Scope:Global
inet6 addr: fe80::20c:29ff:fe10:cf0e/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:112470185 errors:2 dropped:1 overruns:0 frame:0
TX packets:5900249 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2187237130 (2.1 GB) TX bytes:1640094885 (1.6 GB)
Interrupt:19 Base address:0x2000
使用192.168.97.162、0.0.0.0、127.0.0.1、::1运行程序或 2620:1c:8000:190:20c:29ff:fe10:cf0e 工作正常但使用 fe80::20c:29ff:fe10:cf0e 无法创建接受器抛出“无效参数”异常。
$ ./asio-ipv6 fe80::20c:29ff:fe10:cf0e
IP Set to fe80::20c:29ff:fe10:cf0e
Valid IP address fe80::20c:29ff:fe10:cf0e
Created endpoint
Error caught: Invalid argument
Done!
这让我想起了使用 ping6 并看到相同的“无效参数”错误。解决方法是传递附加到 IPv6 地址的接口(interface)。
$ ping6 fe80::219:b9ff:fe2b:3a53 #Won't work
connect: Invalid argument
$ ping6 fe80::219:b9ff:fe2b:3a53%eth0 #Pass the interface to use to ping6
PING fe80::219:b9ff:fe2b:3a53%eth0(fe80::219:b9ff:fe2b:3a53) 56 data bytes
当我尝试从字符串创建 IP 地址时,这似乎不适用于 Boost Asio。
$ ./asio-ipv6 fe80::20c:29ff:fe10:cf0e%eth0
IP Set to fe80::20c:29ff:fe10:cf0e%eth0
Error caught: Invalid argument
Done!
我的问题是您如何使用 Boost ASIO 监听链接范围的 IPv6 地址? boost::asio::ip::address_v6
类有一个 scope_id() member function但我不确定从哪里获取 scope id 作为 unsigned long 或者这是否是问题所在。
最佳答案
这可以使用 boost::asio::ip::tcp::resolver
--- ipv6.cc.orig 2012-04-24 12:03:02.349911481 -0500
+++ ipv6.cc 2012-04-24 12:02:07.053037095 -0500
@@ -10,42 +10,67 @@
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> TcpSocketPtr;
typedef boost::shared_ptr<boost::asio::ip::tcp::acceptor> TcpAcceptorPtr;
+typedef boost::shared_ptr<boost::asio::ip::tcp::resolver> TcpResolverPtr;
typedef boost::shared_ptr<boost::asio::ip::tcp::endpoint> TcpEndpointPtr;
class AsioServer{
public:
AsioServer(boost::asio::io_service& io): io_(io){};
- //throws
- void accept(const std::string& ipString,unsigned short port){
- boost::asio::ip::address addr = boost::asio::ip::address::from_string(ipString);
- std::cout << "Valid IP address " << ipString << std::endl;
-
- this->endpoint_.reset(new boost::asio::ip::tcp::endpoint(addr,port));
- std::cout << "Created endpoint" << std::endl;
-
- //Will throw if a link local IPv6 address is used
- acceptor_.reset(new boost::asio::ip::tcp::acceptor(this->io_,*(this->endpoint_)));
-
- std::cout << "About to accept on " << *(this->endpoint_) << std::endl;
- this->socket_.reset(new boost::asio::ip::tcp::socket(this->io_));
- this->acceptor_->async_accept(*socket_ ,boost::bind(&AsioServer::handle_accept,this,boost::asio::placeholders::error));
+ void resolve(const std::string& ipString, const std::string& service){
+ this->resolver_.reset(new boost::asio::ip::tcp::resolver(io_));
+ boost::asio::ip::tcp::resolver::query query( ipString, service );
+ this->resolver_->async_resolve( query, boost::bind( &AsioServer::handle_resolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator ) );
}
-
private:
boost::asio::io_service& io_;
TcpSocketPtr socket_;
TcpAcceptorPtr acceptor_;
TcpEndpointPtr endpoint_;
+ TcpResolverPtr resolver_;
+
+ void accept(const boost::asio::ip::tcp::resolver::iterator iterator) {
+ endpoint_.reset(new boost::asio::ip::tcp::endpoint(iterator->endpoint()));
+ //Will throw if a link local IPv6 address is used
+ acceptor_.reset(new boost::asio::ip::tcp::acceptor(this->io_));
+ acceptor_->open(this->endpoint_->protocol());
+ acceptor_->bind(*(this->endpoint_));
+ acceptor_->listen();
+
+
+ std::cout << "About to accept on " << *(this->endpoint_) << std::endl;
+ socket_.reset(new boost::asio::ip::tcp::socket(this->io_));
+ acceptor_->async_accept(*socket_ ,boost::bind(&AsioServer::handle_accept,this,boost::asio::placeholders::error));
+ }
+
void handle_accept(const boost::system::error_code &ec){
if(!ec){
std::cout << "Accepted connection!" << std::endl;
}
else{
- std::cout << "Error accepting connection" << std::endl;
+ std::cout << "Error accepting connection: " << boost::system::system_error(ec).what() << std::endl;
+ }
+ }
+
+ void handle_resolve(
+ const boost::system::error_code& ec,
+ boost::asio::ip::tcp::resolver::iterator iterator
+ )
+ {
+ if(ec) {
+ std::cerr << "could not resolve: " << boost::system::system_error(ec).what() << std::endl;
+ return;
}
- };
+
+ if ( iterator == boost::asio::ip::tcp::resolver::iterator() ) {
+ std::cerr << "no endpoints resolved" << std::endl;
+ return;
+ }
+
+ this->accept(iterator);
+
+ }
};
@@ -62,7 +87,7 @@
AsioServer server(io);
try{
- server.accept(ipString,4444);
+ server.resolve(ipString,"4444");
}
catch(const std::exception& e){
std::cout << "Error caught: " << e.what() << std::endl;
示例 session
[samm@t410 Desktop]$ ifconfig | grep fe80
inet6 addr: fe80::5a94:6bff:fe7c:e760/64 Scope:Link
[samm@t410 Desktop]$ g++ -g ipv6.cc -lboost_system -lboost_thread-mt
[samm@t410 Desktop]$ ./a.out fe80::5a94:6bff:fe7c:e760%wlan0
IP Set to fe80::5a94:6bff:fe7c:e760%wlan0
About to accept on [fe80::5a94:6bff:fe7c:e760%wlan0]:4444
^C
[samm@t410 Desktop]$
关于c++ - 使用 Boost Asio 接受 IPv6 链接范围地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10286042/
我正在本地编程应用程序,但是当我迁移到服务器时,使用此行出现解析错误: if(!is_array($data[array_keys($data)[0]])) 返回值: Parse error: syn
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
我已经开始尝试用 C++ 学习 Winsock,但我遇到了一些问题。我首先遵循 MSDN 上的 Winsock 示例(一个基本的客户端-服务器)。 http://msdn.microsoft.com/
我有一段使用 epoll 的代码,但它有问题。当我运行它时,它给出输出:服务器套接字()没问题......服务器绑定(bind)()没问题......3个4个接受:无效参数 我在 ubuntu lin
我正在寻找一种方法来接受 $_GET 变量作为文件路径,例如 - /page/test将转换为 page.php?page=test .我已经搜索过,但找不到任何可以帮助我的东西,因此我在这里问。 我
我想要一个只接受从 0 到 9 和减号的浮点数的正则表达式。 请帮忙。 最佳答案 ^[-+]?[0-9]*\.?[0-9]+$ ^ - 字符串开头 [-+]? - 0 或 1 符号指示符 [0-9]*
请问如何接受\r\n无需将其更改为 \\r\\n , 与 fgets . 我想让程序翻译 \r\n到换行符而不是将其打印为字符串。 当前代码: char buff[1024]; printf("Msg
我正在编写一个 Cocoa 应用程序,该应用程序需要在其 Dock 图标上接受已安装卷的滴落。它不是基于文档的;我打算将每个卷分派(dispatch)到 application:openFiles 中
我在 SQLite 中发现了这种意外行为。 SQLite 似乎接受 SQL 连接语法中的任意关键字。如果我不小心键入了 natural join 而不是 natural join,则会生成笛卡尔积。这
我在 Windows 窗体的同一个窗体上有一个 TreeView 和一个多行文本框。我有拖放设置,以便我可以将节点从 TreeView 拖到文本框并将文本插入文本框(这是有效的)。 我想增强这一点,以
我正在创建一棵类似于 D3 Layout Tree 的树并尝试绑定(bind)我的自定义 JSON 对象。切换树节点的代码如下。 function toggleAll(d) { if (d.c
所以,我希望能够向我的 DOB 字段发送空选项。 这是我的表单生成器: ->add('birthDate', DateType::class, array( 'widg
错误可以在这里看到:http://djaffry.selfip.com:8080/ 我希望索引页接受参数,无论是 mysite.com/search/param_here 或 mysite.com/?
我想知道标准 Scala 解析器组合器是否包含一个解析器,该解析器接受 Scala 语言本身也接受的相同标识符(如 Scala 语言规范第 1.1 节中所指定)。 StdTokenParsers 特征
我暂时使用以下行在我的 Android 手机上创建 ServerSocket: socketl = new ServerSocket(port, 0, InetAddress.getByName("1
今天早上刚刚发布了一个应用程序,我在所有可能的设备和模拟器上测试了它,但是当我从商店下载它时,应用程序在启动时崩溃。我在很多设备和iOS版本上测试过,但结果都是一样的: Incident Identi
我想要 5 个名字中最长的一个。我想我应该使用 compareTo() 方法或 length()? 输出必须是这样的: enter 5 names : Joey Mark Catherine Zach
抱歉,我不熟悉泛型,我可以创建一个如下所示的泛型类: public class InfoField { } 上面的类可以接受如下值: , User> 但是我可以有接受 map 对象作为值的类吗?
我想让一个单元格等于它上面的单元格。 当我写作时 =address(row()-1;column()) 它只是写入上面单元格的名称(例如,对于 B2,它写入 $B$1) 是否有一个函数可以输入地址并放
我正在使用Asm访问java字节码来获取方法信息。看来ClassReader类的accept方法是异步调用的,所以不可能立即获取方法信息。我该怎么办? 最佳答案 实际上,accept 方法是从您自己的
我是一名优秀的程序员,十分优秀!