<tfoot id='3EyQd'></tfoot>
  • <legend id='3EyQd'><style id='3EyQd'><dir id='3EyQd'><q id='3EyQd'></q></dir></style></legend>
      • <bdo id='3EyQd'></bdo><ul id='3EyQd'></ul>

      1. <small id='3EyQd'></small><noframes id='3EyQd'>

        <i id='3EyQd'><tr id='3EyQd'><dt id='3EyQd'><q id='3EyQd'><span id='3EyQd'><b id='3EyQd'><form id='3EyQd'><ins id='3EyQd'></ins><ul id='3EyQd'></ul><sub id='3EyQd'></sub></form><legend id='3EyQd'></legend><bdo id='3EyQd'><pre id='3EyQd'><center id='3EyQd'></center></pre></bdo></b><th id='3EyQd'></th></span></q></dt></tr></i><div id='3EyQd'><tfoot id='3EyQd'></tfoot><dl id='3EyQd'><fieldset id='3EyQd'></fieldset></dl></div>

      2. boost::asio + std::future - 关闭套接字后访问冲突

        时间:2023-05-23

          <small id='Ik3ZJ'></small><noframes id='Ik3ZJ'>

            <i id='Ik3ZJ'><tr id='Ik3ZJ'><dt id='Ik3ZJ'><q id='Ik3ZJ'><span id='Ik3ZJ'><b id='Ik3ZJ'><form id='Ik3ZJ'><ins id='Ik3ZJ'></ins><ul id='Ik3ZJ'></ul><sub id='Ik3ZJ'></sub></form><legend id='Ik3ZJ'></legend><bdo id='Ik3ZJ'><pre id='Ik3ZJ'><center id='Ik3ZJ'></center></pre></bdo></b><th id='Ik3ZJ'></th></span></q></dt></tr></i><div id='Ik3ZJ'><tfoot id='Ik3ZJ'></tfoot><dl id='Ik3ZJ'><fieldset id='Ik3ZJ'></fieldset></dl></div>

                <legend id='Ik3ZJ'><style id='Ik3ZJ'><dir id='Ik3ZJ'><q id='Ik3ZJ'></q></dir></style></legend>

                  <bdo id='Ik3ZJ'></bdo><ul id='Ik3ZJ'></ul>
                    <tbody id='Ik3ZJ'></tbody>

                • <tfoot id='Ik3ZJ'></tfoot>
                • 本文介绍了boost::asio + std::future - 关闭套接字后访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  限时送ChatGPT账号..

                  我正在编写一个简单的 tcp 客户端来发送和接收单行文本.异步操作由 std::future 处理,以促进具有超时的阻塞查询.不幸的是,我的测试应用程序在破坏服务器对象时因访问冲突而崩溃.这是我的代码:

                  I am writing a simple tcp client to send and receive single lines of text. The asynchronous operations are handled by std::future in order to faciliate blocking queries with timeouts. Unfortunately, my test application crashes with an access violation when destructing the server object. Here is my code:

                  TCPClient.hpp

                  TCPClient.hpp

                  #ifndef __TCPCLIENT_H__
                  #define __TCPCLIENT_H__
                  
                  #include <boost/asio.hpp>
                  #include <boost/asio/use_future.hpp>
                  #include <memory>
                  #include <vector>
                  #include <future>
                  #include <thread>
                  #include <chrono>
                  #include <iostream>
                  #include <iterator>
                  
                  using namespace boost::asio;
                  
                  class TCPClient {
                  public:
                      TCPClient();
                      ~TCPClient();
                  
                      void connect(const std::string& address, const std::string& port);
                      void disconnect();
                  
                      std::string sendMessage(const std::string& msg);
                  private:
                      boost::asio::io_service ioservice;
                      boost::asio::io_service::work work;
                      std::thread t;
                  
                      std::unique_ptr<boost::asio::ip::tcp::socket> socket;
                  };
                  
                  inline TCPClient::TCPClient() : ioservice(), work(ioservice) {
                      t = std::thread([&]() {
                          try {
                              ioservice.run();
                          }
                          catch (const boost::system::system_error& e) {
                              std::cerr << e.what() << std::endl;
                          }
                      });
                  }
                  
                  inline TCPClient::~TCPClient() {
                      disconnect();
                      ioservice.stop();
                      if (t.joinable()) t.join();
                  }
                  
                  inline void TCPClient::connect(const std::string& address, const std::string& port) {
                      socket.reset(new ip::tcp::socket(ioservice));
                  
                      ip::tcp::resolver::query query(address, port);
                      std::future<ip::tcp::resolver::iterator> conn_result = async_connect(*socket, ip::tcp::resolver(ioservice).resolve(query), use_future);
                  
                      if (conn_result.wait_for(std::chrono::seconds(6)) != std::future_status::timeout) {
                          conn_result.get(); // throws boost::system::system_error if the operation fails
                      }
                      else {
                          //socket->close();
                          // throw timeout_error("Timeout");
                          throw std::exception("timeout");
                      }
                  }
                  
                  inline void TCPClient::disconnect() {
                      if (socket) {
                          try {
                              socket->shutdown(ip::tcp::socket::shutdown_both);
                              std::cout << "socket points to " << std::addressof(*socket) << std::endl;
                              socket->close();
                          }
                          catch (const boost::system::system_error& e) {
                              // ignore
                              std::cerr << "ignored error " << e.what() << std::endl;
                          }
                      }
                  }
                  
                  inline std::string TCPClient::sendMessage(const std::string& msg) {
                      auto time_over = std::chrono::system_clock::now() + std::chrono::seconds(4);
                  
                      /*
                      // Doesn't affect the error
                      std::future<size_t> write_fut = boost::asio::async_write(*socket, boost::asio::buffer(msg), boost::asio::use_future);
                  
                      try {
                          write_fut.get();
                      }
                      catch (const boost::system::system_error& e) {
                          std::cerr << e.what() << std::endl;
                      }
                      */
                      boost::asio::streambuf response;
                  
                      std::future<std::size_t> read_fut = boost::asio::async_read_until(*socket, response, '
                  ', boost::asio::use_future);
                      if (read_fut.wait_until(time_over) != std::future_status::timeout) {
                          std::cout << "read " << read_fut.get() << " bytes" << std::endl;
                          return std::string(std::istreambuf_iterator<char>(&response), std::istreambuf_iterator<char>());
                      }
                      else {
                          std::cout << "socket points to " << std::addressof(*socket) << std::endl;
                          throw std::exception("timeout");
                      }
                  }
                  #endif
                  

                  main.cpp

                  #include <iostream>
                  
                  #include "TCPClient.hpp"
                  
                  int main(int argc, char* argv[]) {
                      TCPClient client;
                      try {
                          client.connect("localhost", "27015");
                          std::cout << "Response: " << client.sendMessage("Hello!") << std::endl;
                      }
                      catch (const boost::system::system_error& e) {
                          std::cerr << e.what() << std::endl;
                      }
                      catch (const std::exception& e) {
                          std::cerr << e.what() << std::endl;
                      }
                      system("pause");
                      return 0;
                  }
                  

                  输出是预期的超时"(测试服务器故意不发送数据),但是ioservice.run()TCPClient中关闭套接字后立即崩溃(访问冲突)::disconnect().我是不是在这里做一些内存管理不当?

                  The output is "timeout" as expected (test server sends no data on purpose), but ioservice.run() crashes immediately (access violation) after closing the socket in TCPClient::disconnect(). Am I doing some memory mismanagment here?

                  编译器是 MSVC 12.0.31101.00 Update 4 (Visual Studio 2013)

                  Compiler is MSVC 12.0.31101.00 Update 4 (Visual Studio 2013)

                  推荐答案

                  recvmsg 正在接收到一个缓冲区 (streambuf),该缓冲区在 TCPClient::sendMessage(第 105 行,范围结束).

                  recvmsg is receiving into a buffer (streambuf) that was freed after throwing the exception in TCPClient::sendMessage (line 105, end of scope).

                  您忘记取消在第 97 行开始的异步操作 (async_read_until).修复它:

                  You forgot to cancel the asynchronous operation (async_read_until) started in line 97. Fix it:

                  else {
                      socket->cancel(); // ADDED
                      std::cout << "socket points to " << std::addressof(*socket) << std::endl;
                      throw std::runtime_error("timeout");
                  }
                  

                  甚至只是

                      socket.reset(); // ADDED
                  

                  其他超时路径也是如此.

                  Same goes for other timeout paths.

                  这篇关于boost::asio + std::future - 关闭套接字后访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:未存储返回值时,std::async 不会产生新线程 下一篇:在 C++11 中实现 future::then() 等价于异步执行

                  相关文章

                  最新文章

                • <legend id='axnKv'><style id='axnKv'><dir id='axnKv'><q id='axnKv'></q></dir></style></legend>
                    <bdo id='axnKv'></bdo><ul id='axnKv'></ul>

                  1. <i id='axnKv'><tr id='axnKv'><dt id='axnKv'><q id='axnKv'><span id='axnKv'><b id='axnKv'><form id='axnKv'><ins id='axnKv'></ins><ul id='axnKv'></ul><sub id='axnKv'></sub></form><legend id='axnKv'></legend><bdo id='axnKv'><pre id='axnKv'><center id='axnKv'></center></pre></bdo></b><th id='axnKv'></th></span></q></dt></tr></i><div id='axnKv'><tfoot id='axnKv'></tfoot><dl id='axnKv'><fieldset id='axnKv'></fieldset></dl></div>

                    <small id='axnKv'></small><noframes id='axnKv'>

                    <tfoot id='axnKv'></tfoot>