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 轉換單一顏色)
主站蜘蛛池模板: 叉车电池-叉车电瓶-叉车蓄电池-铅酸蓄电池-电动叉车蓄电池生产厂家 | 北京乾茂兴业科技发展有限公司 | 风淋室生产厂家报价_传递窗|送风口|臭氧机|FFU-山东盛之源净化设备 | 动物解剖台-成蚊接触筒-标本工具箱-负压实验台-北京哲成科技有限公司 | 东莞办公家具厂家直销-美鑫【免费3D效果图】全国办公桌/会议桌定制 | 好物生环保网、环保论坛 - 环保人的学习交流平台 | 贵州成人高考网_贵州成考网 | 北京普辉律师事务所官网_北京律师24小时免费咨询|法律咨询 | 背压阀|减压器|不锈钢减压器|减压阀|卫生级背压阀|单向阀|背压阀厂家-上海沃原自控阀门有限公司 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 德国EA可编程直流电源_电子负载,中国台湾固纬直流电源_交流电源-苏州展文电子科技有限公司 | 清管器,管道清管器,聚氨酯发泡球,清管球 - 承德嘉拓设备 | 对辊式破碎机-对辊制砂机-双辊-双齿辊破碎机-巩义市裕顺机械制造有限公司 | 集装箱展厅-住人集装箱住宿|建筑|房屋|集装箱售楼处-山东锐嘉科技工程有限公司 | 谈股票-今日股票行情走势分析-牛股推荐排行榜 | 电采暖锅炉_超低温空气源热泵_空气源热水器-鑫鲁禹电锅炉空气能热泵厂家 | 预制直埋蒸汽保温管-直埋管道-聚氨酯发泡保温管厂家 - 唐山市吉祥保温工贸有限公司 | SOUNDWELL 编码器|电位器|旋转编码器|可调电位器|编码开关厂家-广东升威电子制品有限公司 | 压缩空气检测_气体_水质找上海京工-服务专业、价格合理 | 纸张环压仪-纸张平滑度仪-杭州纸邦自动化技术有限公司 | 车件|铜件|车削件|车床加工|五金冲压件-PIN针,精密车件定制专业厂商【东莞品晔】 | 光泽度计_测量显微镜_苏州压力仪_苏州扭力板手维修-苏州日升精密仪器有限公司 | 江西高职单独招生-江西单招考试-江西高职单招网 | 石栏杆_青石栏杆_汉白玉栏杆_花岗岩栏杆 - 【石雕之乡】点石石雕石材厂 | 广东泵阀展|阀门展-广东国际泵管阀展览会 | 称重传感器,测力传感器,拉压力传感器,压力变送器,扭矩传感器,南京凯基特电气有限公司 | 水成膜泡沫灭火剂_氟蛋白泡沫液_河南新乡骏华消防科技厂家 | 旋振筛|圆形摇摆筛|直线振动筛|滚筒筛|压榨机|河南天众机械设备有限公司 | 轴承振动测量仪电箱-轴承测振动仪器-测试仪厂家-杭州居易电气 | 煤粉取样器-射油器-便携式等速飞灰取样器-连灵动 | 污水/卧式/潜水/钻井/矿用/大型/小型/泥浆泵,价格,参数,型号,厂家 - 安平县鼎千泵业制造厂 | 电动不锈钢套筒阀-球面偏置气动钟阀-三通换向阀止回阀-永嘉鸿宇阀门有限公司 | 120kv/2mA直流高压发生器-60kv/2mA-30kva/50kv工频耐压试验装置-旭明电工 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 双段式高压鼓风机-雕刻机用真空泵-绍兴天晨机械有限公司 | 臻知网大型互动问答社区-你的问题将在这里得到解答!-无锡据风网络科技有限公司 | 浩方智通 - 防关联浏览器 - 跨境电商浏览器 - 云雀浏览器 | 螺旋绞龙叶片,螺旋输送机厂家,山东螺旋输送机-淄博长江机械制造有限公司 | 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 高考志愿规划师_高考规划师_高考培训师_高报师_升学规划师_高考志愿规划师培训认证机构「向阳生涯」 | 齿轮减速机电机一体机_齿轮减速箱加电机一体化-德国BOSERL蜗轮蜗杆减速机电机生产厂家 | 维泰克Veertek-锂电池微短路检测_锂电池腐蚀检测_锂电池漏液检测 |