“signal”: 不是“`global namespace'”的成员
“signal”: 找不到标识符
工程添加ASIO源码,编译提示出错:
“signal”: 不是“`global namespace'”的成员
“signal”: 找不到标识符
相关代码出错位置:
void asio_signal_handler(int signal_number)
{
#if defined(ASIO_WINDOWS) \
|| defined(ASIO_WINDOWS_RUNTIME) \
|| defined(__CYGWIN__)
signal_set_service::deliver_signal(signal_number);
#else // defined(ASIO_WINDOWS)
// || defined(ASIO_WINDOWS_RUNTIME)
// || defined(__CYGWIN__)
int saved_errno = errno;
signal_state* state = get_signal_state();
signed_size_type result = ::write(state->write_descriptor_,
&signal_number, sizeof(signal_number));
(void)result;
errno = saved_errno;
#endif // defined(ASIO_WINDOWS)
// || defined(ASIO_WINDOWS_RUNTIME)
// || defined(__CYGWIN__)
#if defined(ASIO_HAS_SIGNAL) && !defined(ASIO_HAS_SIGACTION)
::signal(signal_number, asio_signal_handler);
#endif // defined(ASIO_HAS_SIGNAL) && !defined(ASIO_HAS_SIGACTION)
}
原因
通过VAssistX的Go按钮,查看其对应的头文件所在路径和文件名称。发现文件路径是C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt路径中找到声明文件,该函数声明在signal.h文件中
目的平台SDK选择8.1,但是8.1SDK没有安装对应的头文件,,但是系统安装了其他版本的SDK,在C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt路径中找到声明文件
可以安装8.1SDK的开发包,也可以直接引入头文件,毕竟仅仅是告知编译器其函数声明
解决方案
方案一:将工程SDK切换到10.0.10240.0
方案二:C/C++常规/附加目录添加C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
通过VAssistX的Go按钮,查看其对应的头文件所在路径和文件名称。目的平台SDK选择8.1,但是8.1SDK没有安装对应的头文件,该函数声明在signal.h文件中,但是系统安装了其他版本的SDK,在C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt路径中找到声明文件
同步连接超时设置失败
boost库中的asio模块,在阻塞模式下,调用connect进行服务器的连接,如果服务器没有打开,默认情况下需要20秒的超时连接,才会返回。目前尝试设置套接字的连接超时时间,都不奏效。估计只能修改boost源码中的超时时间
//设置成非阻塞,然后调用select等待超时,无效
int TestBoostAsioConnectTimeout()
{
boost::asio::io_service ios;
boost::asio::ip::tcp::socket sock(ios);
boost::system::error_code ec;
sock.open(boost::asio::ip::tcp::v4());
// 设为非阻塞
sock.io_control(boost::asio::ip::tcp::socket::non_blocking_io(true));
sock.connect(
boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string("192.168.1.1"), 80)
, ec);
fd_set fdWrite;
FD_ZERO(&fdWrite);
FD_SET(sock.native(), &fdWrite);
timeval tv = { 5 }; // 5秒超时
if (select(0, NULL, &fdWrite, NULL, &tv) <= 0
|| !FD_ISSET(sock.native(), &fdWrite))
{
std::cout << "连接超时" << std::endl;
sock.close();
return 0;
}
// 设回阻塞
sock.io_control(boost::asio::ip::tcp::socket::non_blocking_io(false));
std::cout << "连接成功" << std::endl;
sock.close();
return 0;
}
//获取原始的套接字,进行属性的设置
int TestBoostAsioConnectOverTime()
{
boost::asio::io_service ios;
boost::asio::ip::tcp::socket sock(ios);
boost::system::error_code ec;
sock.open(boost::asio::ip::tcp::v4());
// 设为非阻塞
sock.io_control(boost::asio::ip::tcp::socket::non_blocking_io(true));
int timeout = 3000;
int nRet = setsockopt(sock.native(), SOL_SOCKET, SO_CONNECT_TIME, (const char*)&timeout, sizeof(timeout));
nRet = setsockopt(sock.native(), SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
sock.connect(
boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string("192.168.1.1"), 80)
, ec);
fd_set fdWrite;
FD_ZERO(&fdWrite);
FD_SET(sock.native(), &fdWrite);
timeval tv;
tv.tv_sec = 1; // 5秒超时
tv.tv_usec = 0;
if (select(0, NULL, &fdWrite, NULL, &tv) <= 0
|| !FD_ISSET(sock.native(), &fdWrite))
{
std::cout << "超时/出错啦" << std::endl;
sock.close();
return 0;
}
// 设回阻塞
sock.io_control(boost::asio::ip::tcp::socket::non_blocking_io(false));
std::cout << "连接成功" << std::endl;
sock.close();
return 0;
}
设置超时的代码:
windows:
int nTvlen=1000; //1s
int retOpt=setsockopt(m_Socket,SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTvlen,sizeof(nTvlen));
linux:
struct timeval nTvlen={1,0}; //1S
int retOpt=setsockopt(m_Socket,SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTvlen,sizeof(nTvlen));
TIME_WAIT
使用Boost库asio组件的时候,建立的套接字,如果没有设置TIME_WAIT的资源销毁时间,会导致网络套接字回收缓慢,建议使用代码如下:
io_service iosev;
ip::tcp::socket socket(iosev);
socket.open(boost::asio::ip::tcp::v4());
//TIME_WAIT回收资源时间
boost::asio::socket_base::linger option(true, 0);
socket.set_option(option);
boost::asio::error::eof(2) end_of_file
BOOST中read_some和 boost::asio::error::eof(2)错误
当socket读写完成调用回调函数时候一定要检查 是不是有EOF错误,如果有那么好了,另一方已经断开连接了别无选择,你也断开吧
boost的async_read()方法报end_of_file错误的可能原因是连接的另一方关闭了,比如A是服务端,B是客户端,B连接上A,和A 通信一段时间后,B关闭了连接,这个时候,如果A 再调用async_read()就会报end_of_file错误
boost::system::error_code
配置连接IP地址和端口的时候,需要注意如果传递的IP地址如下:"537MainStreet"会导致程序崩溃异常如果没有使用ec捕获异常
ip::tcp::endpoint ep(ip::address_v4::from_string(strIP), nPort);
正确代码
boost::system::error_code ec;
ip::tcp::endpoint ep(ip::address_v4::from_string(strIP, ec), nPort);
采用asio库的时候,需要更多的注意ec的使用,否则需要使用try catch捕获异常,否则导致程序崩溃
boost 1.70+中的Boost::asio get_io_service()替代方法
它定义了一个宏
#if BOOST_VERSION >= 107000
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
#else
#define GET_IO_SERVICE(s) ((s).get_io_service())
#endif
并替换调用
socket.get_io_service()
复制使用
GET_IO_SERVICE(socket)
asio::io_service被废弃的问题
io_context -> io_service
io_context.post() -> io_context.get_executor().post()
io_context.dispatch() -> io_context.get_executor().dispatch()
io_context::strand -> strand<io_context::executor_type>
there were also changes to composed operation customization hooks - there are only 2 now - boost::asio::associated_allocator and boost::asio::associated_executor , which default to looking for get_allocator(), get_executor(), T::allocator_type, T::executor_type members of the composed operation function object.
asio/buffer.hpp:2731:26: error: missing space between '""' and suffix identifier
inline ASIO_CONST_BUFFER operator ""_buf(const char* data, std::size_t n)
CentOS7版本GCC4.8.5编译ASIO1.3.2版本,需要升级GCC到7版本,采用scl升级GCC