我正在尝试制作asio和SSL的朋友。 一切顺利,但有一件事会造成不便:如何检测对等关闭连接,并将其与同行只是在发送数据中短暂休息时的情况区分开来,目的是在几秒钟之后继续它?

  • 提升1.48
  • OpenSSL 1.0.0e
  • 使用VS10编译为32位代码
  • 使用W7 x64。

我的困惑来自这样一个事实,即普通套接字和SSL流的asio行为是不同的。 如果我使用tcp :: socket - 我在对等关闭连接时收到EOF错误。 但对于boost :: asio :: ssl :: stream - 事实并非如此。 相反,async_read_some在传输字节时返回0,如果我尝试继续从SSL流中读取 - 返回short_error( http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/ streams.html )。

所以,问题是:它是预期的行为,还是我错误配置了什么?

客户端代码段:

class client
{
public:

    // bla-bla-bla-bla-bla ....
    //
   void handle_write(const boost::system::error_code& error)
   {
       if (!error)
       {
           socket_.async_read_some(boost::asio::buffer(reply_, max_length),
               boost::bind(&client::handle_read, this,
               boost::asio::placeholders::error,
               boost::asio::placeholders::bytes_transferred));
       }
       else
       {
           std::cout << "Write failed: " << error.message() << "\n";
       }
   }

   void handle_read(const boost::system::error_code& error,
                   size_t bytes_transferred)
   {

       std::cout << "Bytes transfered: " << bytes_transferred << "\n";
       if (!error)
       {
           std::cout << "Reply: ";
           std::cout.write(reply_, bytes_transferred);
           std::cout << "\n";

           std::cout << "Reading...\n";
           socket_.async_read_some(boost::asio::buffer(reply_, max_length),
               boost::bind(&client::handle_read, this,
               boost::asio::placeholders::error,
               boost::asio::placeholders::bytes_transferred));
       }
       else if (0 != bytes_transferred)
       {
           std::cout << "Read failed: " << error.message() << ":" 
                     << error.value() <<  "\n";
       }
   }

private:
   boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
   boost::asio::streambuf request_;
   char reply_[max_length];
};

如果我们删除if(0!= bytes_transferred),我们将得到“short read”:(。

如果我们将使用代码as-ai,输出将是这样的:

要求是:

GET / HTTP / 1.0

Cookie:Nama-nama = Vala-vala

转移的字节数:1024

回复:HTTP / 1.0 200 ok内容类型:text / html

..... bla-bla-bla ....

阅读...字节转移:1024

..... bla-bla-bla .... ..... bla-bla-bla ....

阅读......字节转移:482

..... bla-bla-bla ....

读...

字节转移:0

同时,如果我们编写代码async_read_some,普通套接字将返回EOF:

boost::asio::async_read(socket_, response_,
    boost::asio::transfer_at_least(1),
    boost::bind(&client::handle_read_content, this,
    boost::asio::placeholders::error));

然后对于SSL套接字,我们将获得0作为字节传输,然后short_read。

我知道,如果对等设备刚刚从网络上拔下,则无法检测到断开连接。 但是,当对等体暂时不发送数据时,如何检测显式干净对等体断开情况,但可能稍后会这样做?

或者,可能是我不懂事?

WBR,安德烈

一些addentum: SSL / TLS有通知其他方关闭连接的表示法。 它close_notify警报。 底层TCP套接字也可以关闭。

所以,基本上,我的问题是:为什么,在相同的条件下(TCP套接字被清楚地关闭)我在tcp :: socket的情况下收到EOF,并且没有收到任何用于boost :: asio :: ssl :: stream的东西。

是bug还是asio功能?

又一个addentum:由于某些原因,如果SSL收到close_notify并且底层的TCP套接字已关闭,asio也没有给我一个EOF。

是的,我可以通过超时检测死连接。 但是,如何检测正确关闭的SSL连接? 通过接收short_read?

===============>>#1 票数:14

此处需要SSL_R_SHORT_READ错误。 当服务器使用SSL_Shutdown启动干净关闭时, SSL_Shutdown向客户端发送关闭通知关闭警报。 Asio实现将此映射为SSL_R_SHORT_READ错误,类别为error::get_ssl_category() 它通过检测对等体是否已通过SSL_get_shutdown启动关闭来实现此SSL_get_shutdown

这可以通过检查asio/ssl/detail/impl/engine.ipp标头,特别是函数engine::map_error_code(boost::system::error_code&)

我相信ssl实现在boost 1.47中被重写,因此早期版本可能有不同的行为。

===============>>#2 票数:6

您可能对以下讨论感兴趣:

基本上,当远程方断开普通TCP套接字时,有时(甚至大部分时间)获得EOF这一事实只是运气。 在一般情况下你不能依赖它,因为它不可能在不写入的情况下区分非活动套接字和套接字突然关闭。

您需要在应用程序协议级别定义一些分隔符,以了解何时停止读取。 在HTTP中,这可以通过结束标题的空行(对于标题),定义主体长度的Content-Length标头,或者在预先不知道主体长度时的分块传输编码分隔符来完成。

  ask by Amdei translate from so

未解决问题?本站智能推荐:

1回复

提升asio ssl async_shutdown总是以错误结束?

我有一个小的ssl客户端,我已经在boost 1.55 asio编程,我想弄清楚为什么boost::asio::ssl::stream::async_shutdown()总是失败。 客户端与boost文档中的ssl客户端示例非常相似(几乎完全相同),因为它通过boost::asio::ip::
1回复

无法实现boost :: asio :: ssl :: stream 重新连接到服务器

我需要实现一个处理连接到SSL服务器的类。 几乎基于此 。 然而。 它没有重新连接功能 。 所以我这样修改它: 至 并重构与->相关的所有内容 但这会导致如下错误: 然后,我尝试取消对指针的引用以保留旧结构,但是出现了新错误:( 请帮助,我来自
1回复

使用Boost Asio建立SSL连接

基本上,a具有用于对服务器进行http调用并处理响应的代码,但是我想保护传输的数据并进行调用https。 为此,我有这个executor.hpp 和这个executor.cpp 以下是编译器上的完整错误
1回复

ssl连接后,boost :: asio发送获取请求

我正在使用boost :: asio,并且一直在查看有关如何连接到ssl主机的示例代码 。 但是我想通过ssl连接到服务器后发送一个get请求,这怎么可能? 我是否像http示例一样发送get请求?
1回复

boost ASIO async_read_until不能与ASIO ssl客户端示例一起编译

从本示例开始,我想用async_read()替换async_read_until() 。 因此,我查看了此示例 ,并看到了如何async_read_until() 。 我看到它的名称如下: 因此,与SSL客户端示例相比,我看到的唯一区别是response_是boost::asio
1回复

提升asio SSL stream.shutdown(ec); 总是有错误,这是boost :: asio :: ssl :: error :: stream_truncated

我尝试使用Boost Asio和Openssl将一些json发布到SSL服务器,我的情况是它总是有问题,当我尝试关闭流时,存在boost :: asio :: ssl :: error :: stream_truncated问题,现在我试图忽略该问题,我不知道该忽略还是做错了什么? Boost
3回复

关闭boost asio ssl套接字时需要调用ssl :: stream :: shutdown吗?

我的代码如下: 每次我调用m_remote_socket.shutdown ,都会得到一个错误。 这种未知错误具有很大的错误值。 但是可以直接调用m_remote_socket.lowest_layer().shutdown()而不调用m_remote_socket.shutdo
1回复

如何获取类型为boost :: asio :: ssl :: stream的套接字的远程端点的ip地址

如何获取类型为boost :: asio :: ssl :: stream的套接字的远程端点的ip地址。 我想像这样打印对等ip,但是不起作用
1回复

boost asio ssl-连接成功后尝试发送请求

我修改了boost附带的客户端示例。 如果我在handle_handshake方法中发送请求,一切都会按预期进行。 我想做的是连接到服务器,成功之后发送一个或多个请求。 如果我尝试在handle_handshake之后发送请求,则会在handle_write例程中收到一条错误消息-未初
3回复

从一个线程中提升asio - SSL async_read和async_write

我知道OpenSSL,boost asio SSL实现是基于的,不允许并发SSL_read()和SSL_write()(即SSL_read()和SSL_write()由不同的线程执行)。 从同一个线程调用SSL套接字上的boost asio async_read()和async_write