C++ 在另一个线程中运行tcp服务器

C++ 在另一个线程中运行tcp服务器,c++,multithreading,boost,boost-asio,C++,Multithreading,Boost,Boost Asio,我正在努力在不同的线程中运行tcp服务器。所以我有这样的想法: #include <ctime> #include <iostream> #include <string> #include <boost/asio.hpp> using boost::asio::ip::tcp; std::string make_daytime_string() { using namespace std; // For time_t, time a

我正在努力在不同的线程中运行tcp服务器。所以我有这样的想法:

#include <ctime>
#include <iostream>
#include <string>

#include <boost/asio.hpp>

using boost::asio::ip::tcp;

std::string make_daytime_string()
{
    using namespace std; // For time_t, time and ctime;
    time_t now = time(0);
    return ctime(&now);
}

class TcpServer
{
private:
    boost::asio::io_context& io_context_;
    boost::asio::ip::tcp::acceptor acceptor_;
    boost::asio::ip::tcp::socket socket_;
    
public:
    TcpServer(boost::asio::io_context& io_context)
        : io_context_{io_context}
        , socket_(io_context_)
        , acceptor_(io_context_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 512))
    {
        acceptor_.accept(socket_);
        std::string message = make_daytime_string();

        boost::system::error_code ignored_error;
        socket_.write_some(boost::asio::buffer(message), ignored_error);
    }
};


int main()
{
    boost::asio::io_context io_cont;
    std::thread t([&io_cont] ()
    {
        TcpServer server(io_cont);
    });

    std::cout << "I want to display it while server is still running";

    t.join();
    return 0;
}
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
std::string make_days_string()
{
使用命名空间std;//表示时间、时间和ctime;
现在时间=时间(0);
返回ctime(&now);
}
类TcpServer
{
私人:
boost::asio::io_context&io_context;
boost::asio::ip::tcp::acceptor-acceptor;
boost::asio::ip::tcp::socket;
公众:
TcpServer(boost::asio::io_上下文和io_上下文)
:io_context{io_context}
,套接字(io\U上下文)
,接受者(io\U上下文,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),512))
{
接受器u0.accept(套接字0);
std::string message=make_days_string();
boost::system::error\u代码被忽略\u错误;
套接字写入(boost::asio::buffer(消息),忽略错误);
}
};
int main()
{
boost::asio::io_上下文io_cont;
标准::线程t([&io_cont]()
{
TcpServer服务器(io_cont);
});

std::cout关于使用
io_上下文
存在一些混淆;您似乎认为操作在上下文上运行,但除非使用
异步
版本,否则它们不会

其他旁注:

  • write\u有些不(需要)发送整个缓冲区。请改用
    boost::asio::write
下面是一个更简单的例子,澄清了困惑:

#include <boost/asio.hpp>
#include <ctime>
#include <iostream>
#include <string>
using namespace std::chrono_literals;
using boost::asio::ip::tcp;

static std::string make_daytime_string()
{
    using namespace std; // For time_t, time and ctime;
    time_t now = time(0);
    return ctime(&now);
}

class TcpServer {
  public:
    void run() {
        tcp::acceptor acceptor_(io_context_, {{}, 5120});

        boost::system::error_code ec;
        while (!ec) {
            auto socket_ = acceptor_.accept();
            std::string message = make_daytime_string();
            boost::asio::write(socket_, boost::asio::buffer(message), ec);
        }
    }
  private:
    boost::asio::io_context io_context_;
};

int main()
{
    auto server = TcpServer{};
    std::thread t([&server]() { server.run(); });

    for (;; std::this_thread::sleep_for(1s))
        std::cout << "I want to display it while server is still running" << std::endl;

    t.join();
}
#包括
#包括
#包括
#包括
使用名称空间std::chrono_文本;
使用boost::asio::ip::tcp;
静态std::string make_days_string()
{
使用命名空间std;//表示时间、时间和ctime;
现在时间=时间(0);
返回ctime(&now);
}
类TcpServer{
公众:
无效运行(){
tcp::接受者接受者(io_上下文{{},5120});
boost::system::error_code ec;
而(!ec){
自动套接字=接受器。接受();
std::string message=make_days_string();
boost::asio::write(套接字),boost::asio::buffer(消息),ec);
}
}
私人:
boost::asio::io_context io_context;
};
int main()
{
自动服务器=TcpServer{};
线程t([&server](){server.run();});
对于(;;std::this_线程::sleep_for(1s))

std::cout在我尝试其他事情时似乎工作正常。知道std::cout延迟到
t1
结束的原因吗?我很难理解当前行为和预期行为之间的确切区别。-从目前的源代码来看,您的代码应该同时做两件事:1)main-thread向控制台输出消息。2)线程
t
打开一个新连接,阻塞,直到有人连接到它为止(例如,通过使用
netcat从控制台打开客户端)然后将其作为字符串发送到当前日期。然后程序结束。代码的行为是否有所不同?这不是它应该的行为方式吗?使用
std::endl
std::flush
进行刷新IO@2b-抱歉,可能我写得不够清楚。我希望程序在我的
std::cout
之后阻塞。现在是即使我先执行stdout,然后执行join,也要先阻塞。正如@sehe所指出的,您必须使用
std::endl
:Modify
std::cout 1刷新输出。如果我是正确的,那么许多对象的构造函数都需要io_上下文,所以即使我不使用它,我也必须指定它。2.尽管我的代码很难看,但它应该工作正常k正确吗?我的意思是为什么在我使用netcat发送请求后出现
std::cout
?1。您不使用轮询接口,但对象使用“执行上下文”要从中获取服务实现,那么您需要。注意,大多数服务对象都采用执行器,而不仅仅是io上下文,这是一种更好的方法来解耦代码。2.不,您的代码根本没有在单独的线程上运行。我解释过这是因为您不使用异步操作,这意味着构造函数中的调用都是异步的在主线程上阻塞。现在我比以前更困惑了。异步I/o与多线程不同,不是吗?是构造函数调用(即使它在新线程中)总是由主线程维护还是怎么回事?是的,是的。构造函数只是函数。它们碰巧在某些上下文中被调用,但它仍然是在同一线程上运行的代码。
./a.out& for a in {1..9}; do sleep .5; nc 127.0.0.1 5120 <<< ''; done
kill %1
I want to display it while server is still running
Mon May 24 17:41:35 2021
I want to display it while server is still running
Mon May 24 17:41:35 2021
Mon May 24 17:41:36 2021
I want to display it while server is still running
Mon May 24 17:41:36 2021
Mon May 24 17:41:37 2021
I want to display it while server is still running
Mon May 24 17:41:37 2021
Mon May 24 17:41:38 2021
I want to display it while server is still running
Mon May 24 17:41:38 2021
Mon May 24 17:41:39 2021