C++ boost::asio挂起_endthreadx intmain(){ boost::asio::io_上下文io_上下文; 服务器服务器(io\ U上下文、套接字\ U地址、套接字\ U端口); std::线程线程服务器([&](){ server.start(); io_context.run(); }); std::thread线程_客户端([&](){ Client&Client=Client::create(套接字地址、套接字端口); client.start(); done=true;//

C++ boost::asio挂起_endthreadx intmain(){ boost::asio::io_上下文io_上下文; 服务器服务器(io\ U上下文、套接字\ U地址、套接字\ U端口); std::线程线程服务器([&](){ server.start(); io_context.run(); }); std::thread线程_客户端([&](){ Client&Client=Client::create(套接字地址、套接字端口); client.start(); done=true;//,c++,c++11,boost,boost-asio,C++,C++11,Boost,Boost Asio,显示的代码对字符串没有任何作用。此外,您也不会显示客户端实例中正在使用的io\u上下文 如前所述,一切都是一个巨大的竞争条件,因为没有一个客户端工作可能会运行,但是您总是在发布client::start的异步操作后立即设置done=true (如果Client::start()实际上是完全同步的,那么这里可能有一个合理的解释,但这确实会使static Client&Client::create(…)的整个存在变得非常奇怪和无用?) 使用线程睡眠是一种反模式,在异步代码中更是如此 无法取消对字符

显示的代码对字符串没有任何作用。此外,您也不会显示
客户端
实例中正在使用的
io\u上下文

如前所述,一切都是一个巨大的竞争条件,因为没有一个客户端工作可能会运行,但是您总是在发布
client::start的异步操作后立即设置
done=true

(如果
Client::start()
实际上是完全同步的,那么这里可能有一个合理的解释,但这确实会使
static Client&Client::create(…)
的整个存在变得非常奇怪和无用?)

使用线程睡眠是一种反模式,在异步代码中更是如此


无法取消对字符串迭代器的引用,因为字符串迭代器已无效

这是MSVC正在工作的一个明显迹象。它只是告诉你有一个编程错误

您的错误导致在字符串迭代器不再有效时使用它们。我看不到它,但99%的时间是由使用缓冲区的异步操作引起的,该缓冲区在异步操作完成之前被销毁(或修改)。简言之:

int main(){
  boost::asio::io_context io_context;
  Server server(io_context, SOCKET_ADDRESS, SOCKET_PORT);

  std::thread thread_server([&]() {
    server.start();
    io_context.run();
  });

  std::thread thread_client([&]() {
    Client &client = Client::create(SOCKET_ADDRESS, SOCKET_PORT);
    client.start();
    done = true; // <-----atomic
  });

  std::thread thread_stop([&]() {
    while (done == false) {
      std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
    server.stop();
  });

  thread_server.join();
  thread_client.join();
  thread_stop.join();
}
建议代码 简化代码,并显示一些提示:

void foo() {
    std::string msg = "message";
    boost::asio::async_write(_socket, boost::asio::buffer(msg), /*...*/);
}
注意有一场启动竞赛。取决于你的运气,第一个
客户端可能会在
服务器开始侦听之前尝试连接。我想这不是你最担心的问题,我将留给读者作为练习


VisualStudio调试C++运行库标准库类型或迭代器可能与发布版本有不同的大小。这意味着不能将C++标准库类型从调试标准库编译的东西传递到发布标准库编译的东西。隐藏的原因是,仅将设置为默认情况下在释放模式下未检测到错误的值。
#include <boost/asio.hpp>
#include <iostream>
#include <iomanip>

using boost::asio::ip::tcp;
using boost::system::error_code;

static std::string const SOCKET_ADDRESS = "127.0.0.1";
static unsigned short const SOCKET_PORT = 6767;

bool check(error_code const& ec, char const* message) {
    std::cout << message << " (" << ec.message() << ")\n";
    return !ec;
}

struct Server {
    boost::asio::io_context& io_;
    Server(boost::asio::io_context& io, std::string host, unsigned short port) : io_(io), host_(host), port_(port) {}

    void start() {
        acc_.set_option(tcp::acceptor::reuse_address(true));
        acc_.listen(5);

        accept_loop();
    }

    void stop() {
        io_.post([this] { // thread safety
            acc_.cancel();
            acc_.close();
        });
    }

  private:
    void accept_loop() {
        acc_.async_accept(sock_, [this](error_code ec) {
            if (check(ec, "accepted")) {
                std::make_shared<Connection>(std::move(sock_))->start();
                accept_loop();
            }
        });
    }

    struct Connection : std::enable_shared_from_this<Connection> {
        tcp::socket sock_;
        std::string buffer_;

        Connection(tcp::socket&& sock) : sock_(std::move(sock)) {}

        ~Connection() {
            error_code ec;
            std::cout << "Disconnected " << sock_.remote_endpoint(ec) << "\n";
        }

        void start() {
            auto self = shared_from_this();

            async_read_until(sock_, boost::asio::dynamic_buffer(buffer_), "\n", [self,this](error_code ec, size_t bytes) {
                 if (check(ec, "received request")) {
                     std::cout << "Request: " << std::quoted(buffer_.substr(0, bytes), '\'') << "\n";
                     if (bytes > 0)
                         std::reverse(buffer_.begin(), buffer_.begin() + bytes - 1); // reverse the request for the response

                     async_write(sock_, boost::asio::buffer(buffer_, bytes), [self,this](error_code ec, size_t bytes) {
                          if (check(ec, "response sent")) {
                              buffer_.erase(0, bytes);
                              start(); // handle more requests, if any
                          }
                     });
                 }
            });
        }
    };

    std::string host_;
    unsigned short port_;

    tcp::acceptor acc_{io_, {boost::asio::ip::address_v4::from_string(host_), port_}};
    tcp::socket sock_{io_};
};

struct Client {
    Client(std::string host, std::string port) : host_(host), port_(port) {}

    void start() { 
        boost::asio::io_context io;

        tcp::socket s(io);
        tcp::resolver r(io);
        connect(s, r.resolve(host_, port_));

        send_request(s, "hello world\n");
        send_request(s, "bye world\n");
    }

  private:
    void send_request(tcp::socket& s, std::string const& request) {
        write(s, boost::asio::buffer(request));

        boost::asio::streambuf sb;
        read_until(s, sb, "\n");

        std::cout << "Received server response: '" << &sb << "'\n";
    }

    std::string host_;
    std::string port_;
};

int main(){
    boost::asio::io_context io_context;
    Server server(io_context, SOCKET_ADDRESS, SOCKET_PORT);
    server.start();

    std::thread thread_server([&]() { io_context.run(); });

    {
        Client client {SOCKET_ADDRESS, std::to_string(SOCKET_PORT)};
        client.start();
    }

    {
        Client client {SOCKET_ADDRESS, std::to_string(SOCKET_PORT)};
        client.start();
    }

    server.stop();
    thread_server.join();
}
accepted (Success)
received request (Success)
Request: 'hello world
'
response sent (Success)
Received server response: 'dlrow olleh
'
received request (Success)
Request: 'bye world
'
response sent (Success)
Received server response: 'dlrow eyb
'
received request (End of file)
Disconnected 127.0.0.1:49778
accepted (Success)
received request (Success)
Request: 'hello world
'
response sent (Success)
Received server response: 'dlrow olleh
'
received request (Success)
Request: 'bye world
'
response sent (Success)
Received server response: 'dlrow eyb
'
received request (End of file)
Disconnected 127.0.0.1:49780
accepted (Operation canceled)