“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