pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

Boost::asio - 如何中斷被阻塞的 tcp 服務器線程?

Boost::asio - how to interrupt a blocked tcp server thread?(Boost::asio - 如何中斷被阻塞的 tcp 服務器線程?)
本文介紹了Boost::asio - 如何中斷被阻塞的 tcp 服務器線程?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我正在開發一個多線程應用程序,其中一個線程充當從客戶端接收命令的 tcp 服務器.該線程使用 Boost 套接字和接受器等待客戶端連接,從客戶端接收命令,將命令傳遞給應用程序的其余部分,然后再次等待.代碼如下:

I'm working on a multithreaded application in which one thread acts as a tcp server which receives commands from a client. The thread uses a Boost socket and acceptor to wait for a client to connect, receives a command from the client, passes the command to the rest of the application, then waits again. Here's the code:

void ServerThreadFunc()
{
    using boost::asio::ip::tcp;
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port_no));

    for (;;)
    {
        //  listen for command connection
        tcp::socket socket(io_service);
        acceptor.accept(socket);

        //  connected; receive command
        boost::array<char,256> msg_buf;
        socket.receive(boost::asio::buffer(msg_buf));

        //  do something with received bytes here
    }
}

該線程的大部分時間都花在對acceptor.accept() 的調用上.目前,線程僅在應用程序退出時終止.不幸的是,這會在 main() 返回后導致崩潰 - 我相信是因為在單例被銷毀后線程試圖訪問應用程序的日志單例.(老實說,我剛來的時候就是這樣.)

This thread spends most of its time blocked on the call to acceptor.accept(). At the moment, the thread only gets terminated when the application exits. Unfortunately, this causes a crash after main() returns - I believe because the thread tries to access the app's logging singleton after the singleton has been destroyed. (It was like that when I got here, honest guv.)

如何在應用程序退出時干凈地關閉此線程?我讀到可以通過從另一個線程關閉套接字來中斷原始套接字上的阻塞 accept() 調用,但這似乎不適用于 Boost 套接字.我嘗試使用 Boost 異步 tcp 回顯服務器示例,但這似乎只是交換了對 acceptor::accept() 的阻塞調用來對 io_service 的阻塞調用::run(),所以我遇到了同樣的問題:一個無法中斷的阻塞調用.有什么想法嗎?

How can I shut this thread down cleanly when it's time for the application to exit? I've read that a blocking accept() call on a raw socket can be interrupted by closing the socket from another thread, but this doesn't appear to work on a Boost socket. I've tried converting the server logic to asynchronous i/o using the Boost asynchronous tcp echo server example, but that just seems to exchange a blocking call to acceptor::accept() for a blocking call to io_service::run(), so I'm left with the same problem: a blocked call which I can't interrupt. Any ideas?

推薦答案

總之,有兩個選擇:

  • 將代碼更改為異步(acceptor::async_accept()async_read),通過 io_service::run() 在事件循環中運行code>,并通過 io_service::stop() 取消.
  • 強制阻塞調用以較低級別的機制(例如信號)中斷.
  • Change code to be asynchronous (acceptor::async_accept() and async_read), run within the event loop via io_service::run(), and cancel via io_service::stop().
  • Force blocking calls to interrupt with lower level mechanics, such as signals.

我會推薦第一個選項,因為它更易于攜帶且更易于維護.要理解的重要概念是 io_service::run() 只會在有待處理的工作時阻塞.當 io_service::stop() 被調用,它會嘗試使 io_service::run() 上阻塞的所有線程盡快返回;它不會中斷同步操作,例如 acceptor::accept()socket::receive(),即使同步操作在事件循環中被調用.需要注意的是,io_service::stop() 是一個非阻塞調用,因此與 io_service::run() 上阻塞的線程同步必須使用另一個機制,例如 thread::join().

I would recommend the first option, as it is more likely to be the portable and easier to maintain. The important concept to understand is that the io_service::run() only blocks as long as there is pending work. When io_service::stop() is invoked, it will try to cause all threads blocked on io_service::run() to return as soon as possible; it will not interrupt synchronous operations, such as acceptor::accept() and socket::receive(), even if the synchronous operations are invoked within the event loop. It is important to note that io_service::stop() is a non-blocking call, so synchronization with threads that were blocked on io_service::run() must use another mechanic, such as thread::join().

這是一個運行 10 秒并偵聽端口 8080 的示例:

Here is an example that will run for 10 seconds and listens to port 8080:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>

void StartAccept( boost::asio::ip::tcp::acceptor& );

void ServerThreadFunc( boost::asio::io_service& io_service )
{
  using boost::asio::ip::tcp;
  tcp::acceptor acceptor( io_service, tcp::endpoint( tcp::v4(), 8080 ) );

  // Add a job to start accepting connections.
  StartAccept( acceptor );

  // Process event loop.
  io_service.run();

  std::cout << "Server thread exiting." << std::endl;
}

void HandleAccept( const boost::system::error_code& error,
                   boost::shared_ptr< boost::asio::ip::tcp::socket > socket,
                   boost::asio::ip::tcp::acceptor& acceptor )
{
  // If there was an error, then do not add any more jobs to the service.
  if ( error )
  {
    std::cout << "Error accepting connection: " << error.message() 
              << std::endl;
    return;
  }

  // Otherwise, the socket is good to use.
  std::cout << "Doing things with socket..." << std::endl;

  // Perform async operations on the socket.

  // Done using the socket, so start accepting another connection.  This
  // will add a job to the service, preventing io_service::run() from
  // returning.
  std::cout << "Done using socket, ready for another connection." 
            << std::endl;
  StartAccept( acceptor );
};

void StartAccept( boost::asio::ip::tcp::acceptor& acceptor )
{
  using boost::asio::ip::tcp;
  boost::shared_ptr< tcp::socket > socket(
                                new tcp::socket( acceptor.get_io_service() ) );

  // Add an accept call to the service.  This will prevent io_service::run()
  // from returning.
  std::cout << "Waiting on connection" << std::endl;
  acceptor.async_accept( *socket,
    boost::bind( HandleAccept,
      boost::asio::placeholders::error,
      socket,
      boost::ref( acceptor ) ) );
}

int main()
{
  using boost::asio::ip::tcp;

  // Create io service.
  boost::asio::io_service io_service;

  // Create server thread that will start accepting connections.
  boost::thread server_thread( ServerThreadFunc, boost::ref( io_service ) );

  // Sleep for 10 seconds, then shutdown the server.
  std::cout << "Stopping service in 10 seconds..." << std::endl;
  boost::this_thread::sleep( boost::posix_time::seconds( 10 ) );
  std::cout << "Stopping service now!" << std::endl;

  // Stopping the io_service is a non-blocking call.  The threads that are
  // blocked on io_service::run() will try to return as soon as possible, but
  // they may still be in the middle of a handler.  Thus, perform a join on 
  // the server thread to guarantee a block occurs.
  io_service.stop();

  std::cout << "Waiting on server thread..." << std::endl;
  server_thread.join();
  std::cout << "Done waiting on server thread." << std::endl;

  return 0;
}

在運行時,我打開了兩個連接.這是輸出:

While running, I opened two connections. Here is the output:

Stopping service in 10 seconds...
Waiting on connection
Doing things with socket...
Done using socket, ready for another connection.
Waiting on connection
Doing things with socket...
Done using socket, ready for another connection.
Waiting on connection
Stopping service now!
Waiting on server thread...
Server thread exiting.
Done waiting on server thread.

這篇關于Boost::asio - 如何中斷被阻塞的 tcp 服務器線程?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Assertion failed (size.widthgt;0 amp;amp; size.heightgt;0)(斷言失敗(size.width0 amp;amp; size.height0))
Rotate an image in C++ without using OpenCV functions(在 C++ 中旋轉圖像而不使用 OpenCV 函數)
OpenCV: process every frame(OpenCV:處理每一幀)
Why can#39;t I open avi video in openCV?(為什么我不能在 openCV 中打開 avi 視頻?)
OpenCV unable to set up SVM Parameters(OpenCV 無法設置 SVM 參數)
Convert a single color with cvtColor(使用 cvtColor 轉換單一顏色)
主站蜘蛛池模板: 短信营销平台_短信群发平台_106短信发送平台-河南路尚 | 吨袋包装机|吨包秤|吨包机|集装袋包装机-烟台华恩科技 | 上海皓越真空设备有限公司官网-真空炉-真空热压烧结炉-sps放电等离子烧结炉 | 济南玻璃安装_济南玻璃门_济南感应门_济南玻璃隔断_济南玻璃门维修_济南镜片安装_济南肯德基门_济南高隔间-济南凯轩鹏宇玻璃有限公司 | 517瓜水果特产网|一个专注特产好物的网站 | 电动高压冲洗车_价格-江苏速利达机车有限公司 | 湿地保护| 全自动烧卖机厂家_饺子机_烧麦机价格_小笼汤包机_宁波江北阜欣食品机械有限公司 | 上海租奔驰_上海租商务车_上海租车网-矢昂汽车服务公司 | 废水处理-废气处理-工业废水处理-工业废气处理工程-深圳丰绿环保废气处理公司 | 河北码上网络科技|邯郸小程序开发|邯郸微信开发|邯郸网站建设 | 水厂自动化-水厂控制系统-泵站自动化|控制系统-闸门自动化控制-济南华通中控科技有限公司 | 一体式钢筋扫描仪-楼板测厚仪-裂缝检测仪-泰仕特(北京) | 在线钠离子分析仪-硅酸根离子浓度测定仪-油液水分测定仪价格-北京时代新维测控设备有限公司 | 航空连接器,航空插头,航空插座,航空接插件,航插_深圳鸿万科 | 中空玻璃生产线,玻璃加工设备,全自动封胶线,铝条折弯机,双组份打胶机,丁基胶/卧式/立式全自动涂布机,玻璃设备-山东昌盛数控设备有限公司 | 万烁建筑设计院-建筑设计公司加盟,设计院加盟分公司,市政设计加盟 | 硅胶管挤出机厂家_硅胶挤出机生产线_硅胶条挤出机_臣泽智能装备 贵州科比特-防雷公司厂家提供贵州防雷工程,防雷检测,防雷接地,防雷设备价格,防雷产品报价服务-贵州防雷检测公司 | 冷热冲击试验箱_温度冲击试验箱价格_冷热冲击箱排名_林频厂家 | 宜兴市恺瑞德环保科技有限公司| 锥形螺带干燥机(新型耙式干燥机)百科-常州丰能干燥工程 | 刑事律师_深圳著名刑事辩护律师_王平聚【清华博士|刑法教授】 | 巨野电机维修-水泵维修-巨野县飞宇机电维修有限公司 | 塑料薄膜_PP薄膜_聚乙烯薄膜-常州市鑫美新材料包装厂 | 穿线管|波纹穿线管|包塑金属软管|蛇皮管?闵彬专注弱电工程? | 螺钉式热电偶_便携式温度传感器_压簧式热电偶|无锡联泰仪表有限公司|首页 | 环比机械| 培训无忧网-教育培训咨询招生第三方平台 | 灌装封尾机_胶水灌装机_软管灌装封尾机_无锡和博自动化机械制造有限公司 | 高考志愿规划师_高考规划师_高考培训师_高报师_升学规划师_高考志愿规划师培训认证机构「向阳生涯」 | 水平筛厂家-三轴椭圆水平振动筛-泥沙震动筛设备_山东奥凯诺矿机 包装设计公司,产品包装设计|包装制作,包装盒定制厂家-汇包装【官方网站】 | 浴室柜-浴室镜厂家-YINAISI · 意大利设计师品牌 | 咿耐斯 |-浙江台州市丰源卫浴有限公司 | 脉冲布袋除尘器_除尘布袋-泊头市净化除尘设备生产厂家 | 医院专用门厂家报价-医用病房门尺寸大全-抗菌木门品牌推荐 | 直流电能表-充电桩电能表-导轨式电能表-智能电能表-浙江科为电气有限公司 | 山东螺杆空压机,烟台空压机,烟台开山空压机-烟台开山机电设备有限公司 | 石磨面粉机|石磨面粉机械|石磨面粉机组|石磨面粉成套设备-河南成立粮油机械有限公司 | 西门子代理商_西门子变频器总代理-翰粤百科 | 智慧旅游_智慧景区_微景通-智慧旅游景区解决方案提供商 | 北京中创汇安科贸有限公司| 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 |