c++异网正确使用接受

原文

正确使用受者

异网受者有通过端点构造的重载函数,创建受者之后就可以接受了,代码如下:

用 异网::ip::传控;
传控::受者 受者(io环境,传控::端点(传控::v4(),端口));
受者.异步接受(套接字,[](异网::错误码 ec){});

该代码一般情况下没问题,但是如果端口被占用就会抛异常,需要注意捕获异常.
如果不希望抛异常,则需要先监听端口再接受,如果监听失败就返回错误码.

传控::受者 受者(io环境);
受者.打开(端点.协议());
受者.置选项(提升::异网::ip::传控::受者::重用地址(真));
异网::错误码 ec;
受者.绑定(端点,ec);
如(ec){
    输出<<"绑定端口失败"<<ec.消息()<<"\n";
    中 ec;
}
受者.听();

这里面需要设置reuse_address选项,为什么要设置它?该选项对重启服务器有帮助,当套接字处于TIME_WAIT状态时,启动服务器,就会绑定失败,报已用地址错误,如果设置了reuse_address(true),则可以绑定成功.为什么第一个例子中不显式设置该参数呢,因为通过端点构造的受者默认参数就是reuse_addr=true.

正确关闭受者

写异步服务器时,需要通过异步循环调用异步接受:

空 服务器::干接受()
{
  受者_.异步接受(
      [本](错误码 ec,异网::ip::传控::套接字 套接字)
      {
        如(!ec)
        {
          连接管_.开始(造共<连接>(
              移动(套接字),连接管_,请求处理器_));
        }异{
            输出<<ec.消息()<<"\n";
        }

        干接受();
      });
}

需要注意错误处理,不像异步读写,它收到错误时不返回,而是继续接受,因为服务器在某一次接受失败时,还可继续接受其它连接,如果返回了,则整个服务器不能响应新连接了.上面代码错误处理还不够,关闭受者后,整个接受就会陷入死循环,一直会接受错误,所以正确处理错误方法是接受之前判断是否已经关闭受者了.

空 服务器::干接受()
{
  受者_.异步接受(
      [本](错误码 ec,异网::ip::传控::套接字 套接字)
      {

        如(!受者_.是打开())
        {
          中;
        }
        ...后面相同,略.

      });
}

关闭受者

空 关闭(){
    错误码 ec
    受者_.关闭(ec);
}

这样,是错误的.会引起不可预测后果,因为受者正在异步接受,这时在另外线程中去关闭它,多线程操作受者会导致未定义行为,表现为有时候异步_接受会返回错误,有时候则会挂起主线程,而不会返回错误.在异步回调模式下,该错误造成影响似乎不太大,但在协程环境下,会导致永远不会返回异步接受的协程,这时如果再重启服务端则会出现客户端连接成功,但永远超时.
正确关闭受者的方法是避免多线程去操作受者,通过提交去关闭它.

空 关闭(){
    异网::提交(受者_.取执行器(),[]{
        错误码 ec
        受者_.关闭(ec);
    });
}

提交受者io环境里,可保证在同一线程里操作受者,确保正确关闭它.

posted @   zjh6  阅读(54)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示