boost::asio 干净地断开连接

2023-12-31

有时 boost::asio 似乎在我想要之前断开连接,即在服务器正确处理断开连接之前。我不确定这是怎么可能的,因为客户端似乎认为它完全发送了消息,但是当服务器发出错误时,它甚至没有读取消息头......在测试期间,这种情况可能只发生五分之一,服务器收到客户端关闭消息,并干净地断开客户端连接。

错误:“现有连接被远程主机强制关闭”

客户端断开连接:

void disconnect()
{
    boost::system::error_code error;
    //just creates a simple buffer with a shutdown header
    boost::uint8_t *packet = createPacket(PC_SHUTDOWN,0);
    //sends it
    if(!sendBlocking(socket,packet,&error))
    {
        //didnt get here in my tests, so its not that the write failed...
        logWrite(LOG_ERROR,"server",
            std::string("Error sending shutdown message.\n")
            + boost::system::system_error(error).what());
    }

    //actaully disconnect
    socket.close();
    ioService.stop();
}
bool sendBlocking(boost::asio::ip::tcp::socket &socket,
    boost::uint8_t *data, boost::system::error_code* error)
{
    //get the length section from the message
    boost::uint16_t len = *(boost::uint16_t*)(data - 3);
    //send it
    asio::write(socket, asio::buffer(data-3,len+3),
        asio::transfer_all(), *error);
    deletePacket(data);
    return !(*error);
}

服务器:

void Client::clientShutdown()
{
    //not getting here in problem cases
    disconnect();
}
void Client::packetHandler(boost::uint8_t type, boost::uint8_t *data,
    boost::uint16_t len, const boost::system::error_code& error)
{
    if(error)
    {
        //error handled here
        delete[] data;
        std::stringstream ss;
        ss << "Error recieving packet.\n";
        ss << logInfo() << "\n";
        ss << "Error: " << boost::system::system_error(error).what();
        logWrite(LOG_ERROR,"Client",ss.str());

        disconnect();
    }
    else
    {
        //call handlers based on type, most will then call startRead when
        //done to get the next packet. Note however, that clientShutdown
        //does not
        ...
    }
}



void startRead(boost::asio::ip::tcp::socket &socket, PacketHandler handler)
{
    boost::uint8_t *header = new boost::uint8_t[3];
    boost::asio::async_read(socket,boost::asio::buffer(header,3),
        boost::bind(&handleReadHeader,&socket,handler,header, 
        boost::asio::placeholders::bytes_transferred,boost::asio::placeholders::error));
}
void handleReadHeader(boost::asio::ip::tcp::socket *socket, PacketHandler handler,
    boost::uint8_t *header, size_t len, const boost::system::error_code& error)
{
    if(error)
    {
        //error "thrown" here, len always = 0 in problem cases...
        delete[] header;
        handler(0,0,0,error);
    }
    else
    {
        assert(len == 3);
        boost::uint16_t payLoadLen  = *((boost::uint16_t*)(header + 0));
        boost::uint8_t  type        = *((boost::uint8_t*) (header + 2));
        delete[] header;
        boost::uint8_t *payLoad = new boost::uint8_t[payLoadLen];

        boost::asio::async_read(*socket,boost::asio::buffer(payLoad,payLoadLen),
            boost::bind(&handleReadBody,socket,handler,
            type,payLoad,payLoadLen,
            boost::asio::placeholders::bytes_transferred,boost::asio::placeholders::error));
    }
}
void handleReadBody(ip::tcp::socket *socket, PacketHandler handler,
    boost::uint8_t type, boost::uint8_t *payLoad, boost::uint16_t len,
    size_t readLen, const boost::system::error_code& error)
{
    if(error)
    {
        delete[] payLoad;
        handler(0,0,0,error);
    }
    else
    {
        assert(len == readLen);
        handler(type,payLoad,len,error);
        //delete[] payLoad;
    }
}

我想你应该打电话给socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec)在打电话之前在那里socket.close().

The basic_stream_socket::close 的 boost::asio 文档 http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/reference/basic_stream_socket/close/overload2.html states:

对于与正常关闭已连接套接字相关的可移植行为,请在关闭套接字之前调用 shutdown()。

这应该确保在调用 socket.close 之前正确取消套接字上的任何挂起操作并刷新所有缓冲区。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

boost::asio 干净地断开连接 的相关文章

随机推荐

  • 强制 Nosetests 使用 Python 2.7 而不是 3.4

    我一直在使用 3 4 版本学习 Python 我最近开始学习 Web py 因此一直使用 Python 2 7 因为 Python 3 4 不支持 web py 我为Python 3 4 和2 7 安装了nose 1 3 4 模块 我需要对
  • SSIS 错误代码:0xC0014009

    如何解决 SQL Server 代理运行作业 SSIS 失败并出现错误代码 0xC0014009 的问题 我的工作 ssis 包将数据从源数据库 interbase 转换到目标 SQL Server 以使用 ODBC 我发现工作失败了 错误
  • ARMAX模型预测在传递exog值时导致“ValueError:矩阵未对齐”

    我正在努力使用 ARMAX 模型预测样本值 拟合模型效果很好 armax mod31 sm tsa ARMA endog sales order 3 1 exog media fit armax mod31 fittedvalues 就我有
  • 带图案边框的自定义 PopOver

    I m trying to implement popover like that 我花了很多时间尝试定制UIPopoverController and UIPopoverBackgroundView 据我了解 使用弹出窗口的公共 API
  • 在函数中使用模板模板参数时出现无匹配函数错误

    我正在尝试使用模板模板参数定义一个函数 我只想知道它是如何工作的 我有以下内容 template
  • MSMQ 获取所有专用队列

    有没有办法使用 NET 4 0 获取 MSMQ 5 0 上的所有队列 干杯 MessageQueue GetPrivateQueuesByMachine http msdn microsoft com en us library syste
  • 删除 Xcode 生成的源代码中的版权

    使用 Xcode 4 创建新的源代码文件时 有什么方法可以完全删除带有版权声明的注释吗 代替 MainView h ProjectName Created by First Last Name on 1 2 34 Copyright c 2
  • Angular 4:何时以及为何在构造函数中使用 @Inject?

    问题陈述 我正在学习 Angular 4 我偶然发现了一段代码 其中 Inject正在使用在constructor我不明白为什么 代码和来源 我正在使用 Angular 4 材质 代码来源 https material angular io
  • 选择特定的 Ubuntu 版本

    如果我使用默认的 travis 文件 那么构建机器似乎是 Ubuntu Precise Hit http ppa launchpad net precise Release gpg 是否有任何调整可以使用值得信赖或乌托邦的机器 现在已经实现
  • 在 Yii2 中覆盖 Bootstrap CSS

    我有一个NavBar我想覆盖 Yii 放在该小部件上的所有类 在搜索谷歌并阅读文档后 我发现这段代码 Yii container gt set yii bootstrap NavBar containerOptions gt class g
  • 如何在 OCR 认知中使用 application/octet-stream 发送图像

    您好 我正在尝试使用 Microsoft 的 OCR API 它期望内容类型应用程序 八位字节流和正文 发布二进制文件 我尝试将图像作为 Base64 二进制 发送 只是二进制 但是它不起作用 有人知道这张图片需要如何发送吗 文档链接 ht
  • 为什么 Path.GetDirectoryName 函数必须依赖于 260 个字符的限制

    public static void Main testing file name var fileName server7 EmailAttachments myfolder abc 2012 1126 e85c6b82 edc5 4ce
  • 使用简单 HTML DOM 循环遍历表格

    我正在使用 Simple HTML DOM 从 HTML 文档中提取数据 但有几个问题需要帮助 在以以下开头的行上if td gt find a 我想分别提取href和锚节点的内容 并将它们放在单独的变量中 然而 该代码不起作用 请参阅下面
  • 如何防止在文本字段中输入特定字符?

    我想知道如何阻止在 UITextfield 中输入某些字符 例如 如果我不希望在此文本字段中键入字母 A G P Q X 但允许其余字母 我对此很陌生 感谢您的帮助 您需要为此使用 UITextViewDelegate 在委托方法之一中捕获
  • 数字格式,写1e-5而不是0.00001

    我用过read table读取包含数字 例如 0 00001 的文件 当我写回它们时write table这些数字显示为 1e 5 如何保留旧格式 我只想改变scipen呼叫前的选项write table 请注意 这也会改变打印到控制台时数
  • Eclipse 中的 ESlint

    我在工作中得到了一个 Web 项目 其中有一个 eslintrc 文件 并被告知使用它 我认为这会强制执行代码样式 听起来是个好主意 但我以前从未这样做过 我刚刚切换到 Eclipse Neon 但我找不到有关如何使用它的教程 我确实发现了
  • HTTP 状态 500 - 过滤器执行引发异常 - doFilter 和 invokeDelegate 重复

    我正在使用 Spring MVC 4 2 5 和 Spring Security 4 1 3 来开发 Web 应用程序 当我尝试将后者合并到我的 mvc 项目中时 我开始遇到问题 目前 经过多次尝试 我在 localhost 8080 Be
  • Google 搜索 API 网站限制

    根据 Google 自定义搜索 API 文档 http code google com apis customsearch docs start html sites http code google com apis customsear
  • Node.js 的编码错误

    我正在用node js 重写一个小的python 脚本 原来的脚本是这样工作的 coding utf 8 import urllib import httplib import json def rpc url args try post
  • boost::asio 干净地断开连接

    有时 boost asio 似乎在我想要之前断开连接 即在服务器正确处理断开连接之前 我不确定这是怎么可能的 因为客户端似乎认为它完全发送了消息 但是当服务器发出错误时 它甚至没有读取消息头 在测试期间 这种情况可能只发生五分之一 服务器收