1. 程式人生 > >boost::asio::io_service與socket(C++)

boost::asio::io_service與socket(C++)

boost::asio::io_service

io_service類為下面的非同步物件提供核心的I/O操作函式,主要用途還是用於socket程式設計

  1. boost::asio::ip::tcp::socket
  2. boost::asio::ip::tcp::acceptor
  3. boost::asio::ip::udp::socket
  4. boost::asio::deadline_timer

io_servie 實現了一個任務佇列,io_servie最常用的兩個介面是post和run,post向任務佇列中投遞任務,run是執行佇列中的任務,直到全部執行完畢,並且run可以被N個執行緒呼叫。Io_service是完全執行緒安全的佇列。

【示例】
該示例通過建立io_service類物件,用於監聽並處理tcp::socket執行緒,以socket形式向遠端傳送資料

//**********定義一個io_service類
boost::asio::io_service ioService;
//**********定義一個socket類
//1、SendSocket為自定義的一個socket類;
//2、SendSocket(boost::asio::io_service& ioService, const std::string& _server, uint16_t _port)為該類的建構函式,進行相應的初始化操作,其中ioService是上面定義的io_service類,_server是接收socket的伺服器,_port接收socket伺服器的埠;
//3、socket(new tcp::socket(ioService))為啟動的socket型別,此處是啟用tcp型別,然後使該socket執行緒關聯io_service,以便後續呼叫io_service類的先關函式; //4、queue是socket用來發送資料的快取結構體; SendSocket::SendSocket(boost::asio::io_service& ioService, const std::string& _server, uint16_t _port) : socket(new tcp::socket(ioService)), packetNo(0), server(_server), port(_port), connecting(false
), connected(false), sending(false), state(TS_RUNNING), sendCount(0), oldSendCount(0), lastLog(0) { if (!_server.empty()) serverAddress = boost::asio::ip::address::from_string(_server); queue = _queue = new PacketInfo(); } //**********守護io_service物件 //由於run函式在io事件完成後會退出,執行緒會終止,後續基於該物件的非同步io任務無法得到排程。 boost::asio::io_service::work work(io_service); io_service.run();

【說明】
1、首先考察非同步IO的處理流程

  1. 應用程式呼叫IO物件成員函式執行IO操作;
  2. IO物件請求io_service的服務;
  3. io_service 通知作業系統其需要開始一個非同步連線;
  4. 作業系統指示連線操作完成, io_service從佇列中獲取操作結果;
  5. 應用程式必須呼叫io_service::run()以便於接收結果;
  6. 呼叫io_service::run()後,io_service返回一個操作結果,並將其翻譯為error_code,傳遞到事件回撥函式中;

2、然後考察io_service物件

io_service物件主要有兩個方法——post和run:

  1. post用於釋出io事件,如timer,socket讀寫等,一般由asio框架相應物件呼叫,無需我們顯式呼叫;
  2. run用於監聽io事件響應,並執行響應回撥,對於非同步io操作需要在程式碼中顯式呼叫;

在非同步io操作中需要我們手動呼叫run函式,基本工作模式如下:

  1. 等待io事件響應,如果所有io事件響應完成則退出;
  2. 等待到io事件響應後,執行其對應的回撥;
  3. 繼續等待下一個io事件,重複1-2;

在使用過程中一般有如下幾個需要注意的地方:

1. run函式在io事件完成後會退出,導致後續基於該物件的非同步io任務無法執行
由於io_service並不會主動排程執行緒,需要我們手動分配,常見的方式是給其分配一個執行緒,然後執行run函式。但run函式在io事件完成後會退出,執行緒會終止,後續基於該物件的非同步io任務無法得到排程。解決這個問題的方法是通過一個asio::io_service::work物件來守護io_service。這樣,即使所有io任務都執行完成,也不會退出,繼續等待新的io任務。

boost::asio::io_service::work work(io_service);
io_service.run();

WSAStartup和WSACleanup

WSAStartup與WSACleanup成對使用,WSAStartup的功能是初始化Winsock DLL,WSACleanup是來解除與Socket庫的繫結並且釋放Socket庫所佔用的系統資源。

在Windows下,Socket是以DLL的形式實現的。在DLL內部維持著一個計數器,只有第一次呼叫WSAStartup才真正裝載DLL,以後的呼叫只是簡單的增加計數器,而WSACleanup函式的功能則剛好相反,每呼叫一次使計數器減1,當計數器減到0時,DLL就從記憶體中被解除安裝!因此,呼叫了多少次WSAStartup,就應相應的呼叫多少次的WSACleanup。
【函式原型】

int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );

【引數】
wVersionRequested:呼叫Windows Sockets API的版本;
lpWSAData :指向WSADATA資料結構的指標,用來接收Windows Sockets實現的細節;
【說明】
本函式必須是應用程式或DLL呼叫的第一個Windows Sockets函式.它允許應用程式或DLL指明Windows Sockets API的版本號及獲得特定Windows Sockets實現的細節.應用程式或DLL只能在一次成功的WSAStartup()呼叫之後才能呼叫進一步的Windows Sockets API函式。
【返回值】
成功 – 0
失敗 –
WSASYSNOTREADY 指出網路通訊依賴的網路子系統還沒有準備好;
WSAVERNOTSUPPORTED 所需的Windows Sockets API的版本未由特定的Windows Sockets實現提供;
WSAEINVAL 應用程式指出的Windows Sockets版本不被該DLL支援;

getaddrinfo和struct addrinfo結構體

【函式原型】

int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints,struct addrinfo **result );

【引數】
hostname:一個主機名或者地址串(IPv4的點分十進位制串或者IPv6的16進位制串);
service:一個服務名或者10進位制埠號數串;
hints:可以是一個空指標,也可以是一個指向某個addrinfo結構的指標,呼叫者在這個結構中填入關於期望返回的資訊型別的暗示。舉例來說:如果指定的服務既支援TCP也支援UDP,那麼呼叫者可以把hints結構中的ai_socktype成員設定成SOCK_DGRAM,使得返回的僅僅是適用於資料報套介面的資訊。
result :通過result指標引數返回一個指向addrinfo結構體連結串列的指標
【返回值】
0: 成功,返回非0: 出錯。
【說明】
getaddrinfo函式能夠處理名字到地址以及服務到埠這兩種轉換,返回的是一個sockaddr 結構的鏈而 不是一個地址清單。它具有協議無關性

結構體



    struct addrinfo {
         int ai_flags; /* customize behavior */
         int ai_family; /* address family */
         int ai_socktype; /* socket type */
         int ai_protocol; /* protocol */
         socklen_t ai_addrlen; /* length in bytes of address */
         struct sockaddr *ai_addr; /* address */
         char *ai_canonname; /* canonical name of host */
         struct addrinfo *ai_next; /* next in list */
         .
         .
         .
       };

ai_family指定了地址族,可取值如下:
AF_INET 2 IPv4
AF_INET6 23 IPv6
AF_UNSPEC 0 協議無關

ai_socktype指定套接字的型別
SOCK_STREAM 1 流
SOCK_DGRAM 2 資料報

在AF_INET通訊域中套接字型別SOCK_STREAM的預設協議是TCP(傳輸控制協議)
在AF_INET通訊域中套接字型別SOCK_DGRAM的預設協議是UDP(使用者資料報協議)

ai_protocol指定協議型別,可取的值取決於ai_address和ai_socktype的值,一般設定為0

相關推薦

boost::asio::io_servicesocketC++

boost::asio::io_service io_service類為下面的非同步物件提供核心的I/O操作函式,主要用途還是用於socket程式設計 boost::asio::ip::tcp::socket boost::asio::ip::tcp::a

Boost Asio庫的學習探究

對於boost庫的強大的能力,相信用過boost的人都知道。筆者作用一個小白,今天開始一一探究boost asio庫的一些東西,這裡著重探究和網路有關的內容。由於之前沒有看過asio的原始碼,這裡不免有疏漏和不足,甚至是錯誤之處,這裡歡迎大家一起來探討。 boost/asi

Boost Asio庫的學習探究

到這裡已經是第三篇文章了,這一章我會來進一步介紹tcp.hpp.上一章我們談到,tcp必須顯示構造且建構函式私有,那麼怎樣來構建tcp的物件呢,這裡使用的是靜態成員函式。這是對類的進一步封裝。 1、 static tcp v4() { ret

讀書筆記--C陷阱缺陷

ase 結果 erro bit 使用 功能 錯誤 多層 gnu 第二章 1. 理解函數聲明 書中分析了復雜的類型聲明方式,也說明了使用typedef聲明會更好理解,推薦大家使用typedef進行函數聲明。 書中類型分析一層一層挖掘,讓讀者可以理解多層嵌套的類型含義,有

讀書筆記--C陷阱缺陷

缺陷 目標 命名 整合 編譯器 修飾 調用 檢查 含義 第四章 1. 連接器 C語言的一個重要思想就是分別編譯:若幹個源程序可在不同的時候單獨進行編譯,恰當的時候整合到一起。 連接器一般與C編譯器分離,其輸入是一組目標模塊(編譯後的模塊)和庫文

更新整理本人所有博文中提供的代碼工具C++,2014.01

jbd mlu osg mef sgd dac gpa irf rtc 說酉讕vuu2c短殉炕<a target="_blank" href="http://weibo.com/u/6212262647">http://weibo.com/u/621226264

c語言函數指針的理解使用學習

c語言深度剖析 amp 強制轉換 else 強制 tab 函數指針 border 低耦合 1.函數指針的定義   顧名思義,函數指針就是函數的指針。它是一個指針,指向一個函數。看例子: 1 2 3 A) char * (*fun1)(char * p1

C++中重載overload、覆蓋override隱藏oversee

acl 普通 evc dft war srx rpo 成員 avt body, table{font-family: 微軟雅黑; font-size: 10pt} table{border-col

指標陣列C++學習筆記 11

一、指向陣列元素的指標 1、定義指向陣列元素的指標 每個陣列元素相當於一個變數,所以定義指向陣列元素的指標與定義指向變數的指標方法相同。例如: int ia[5]; /*定義包含5個數組元素的整型陣列ia*/ int *pi; /*定義指向整型變數的指標變數pi*/ p

FastSocketC/C++、FastSocket.NETC#SuperSocket(純C#) 開源庫的區別、介紹、使用方法

一、FastSocket與SuperSocket  區別 裡面包含了視訊教程。 我們到底選擇哪一款開源的Socket框架?https://blog.csdn.net/abennet/article/details/79399713 二、新浪的FastSocket介紹

資料結構——排序查詢2——希爾排序C++實現

希爾排序原理 希爾排序(Shell’s Sort),也稱為“縮小增量排序”,是一種插入排序類的演算法。最簡單的插入排序,我在上一個專欄的一篇文章C++抽象程式設計——演算法分析(8)——插入排序演算法與分析有提到過,這裡就不再贅述,這裡就只介紹一些我以前沒寫過的演算法。 希爾排序是一

資料結構——排序查詢5——折半查詢C++實現

順序查詢 順序查詢,是一種最直觀的查詢方式。原理閒蕩簡單就是我們正常思維的查詢,從給定的序列出發,依次檢查序列中的每一個專案是否為我們給定的關鍵字。是則查詢成功,否則查詢失敗。 bool searchByOrder(vecter<int> vec){ for(int

資料結構——排序查詢3——氣泡排序C++實現

交換排序演算法 所謂交換,意思是說根據所給的序列,對其中的兩個元素進行大小比較,若為逆序,那麼我們就交換它。這樣就達到了排序的目的。接下來介紹最簡單的交換排序——氣泡排序。 氣泡排序的原理 氣泡排序的原理很簡單,它反覆遍歷要排序的列表,比較每對相鄰的專案,如果它們的順序錯誤則

redis原始碼分析思考十三——字串型別的命令實現(t_string.c)

    在對字串操作的命令中,主要有增加刪查該、批處理操作以及編碼的轉換命令,現在列出對字串物件操作的主要常用命令: 常用命令表 命令 對應操作 時間複雜度

C語言面向物件程式設計:封裝繼承1

最近在用 C 做專案,之前用慣了 C++ ,轉回頭來用C 還真有點不適應。 C++ 語言中自帶面向物件支援,如封裝、繼承、多型等面向物件的基本特徵。 C 原本是面向過程的語言,自身沒有內建這些特性,但我們還是可以利用 C 語言本身已有的特性來實現面向物件的一些基本特徵。接下來我們就一一來細說封裝、繼

ROS影象OpenCV影象格式轉換C++

一、ROS官網Converting between ROS images and OpenCV images (C++) 二、使用cv_bridge遇到的問題 1、標頭檔案 #include <opencv2/imgproc/imgproc.hpp> #includ

C#TCPUDP通訊流程、Tcplistener和Tcpclient進行通訊、UdpClient進行通訊

1.基於Tcp協議的Socket通訊類似於B/S架構,面向連線,不同的是伺服器端可以向客戶端主動的推送訊息 流程順序。可靠性高 (1)建立一個套接字(Socket) (2)繫結伺服器端IP地址及埠號-伺服器端 (3)利用Listen()方法開啟監聽-伺服器端 (4)利用Accep

共用體union列舉enumC++

一、共用體: 共用體(union)是一種資料格式,它能夠儲存不同的資料型別,但只能同時儲存其中的一種型別。也就是說,結構可以同時儲存int、long和double,共用體只能儲存int、long或double。共用體的句法與結構相似,但含義不同。例如: union one

派生類繼承C++學習筆記 31

  ① 繼承,就是從先輩處得到屬性和行為特徵,類的繼承就是新的類從已有類那裡得到已有的特性。   ② 類的派生,即可看作從已有類產生新類的過程。由已有類產生新類時,新類便包含了已有類的特徵,同時也可以加入自己的新特性。   ③ 已有類稱為 基類 或 父類 ,產生的新類稱為 派生類 或 子類。

Ubuntu16.04安裝OpenCV-3.4.3的C++和python版本含anaconda建立的python環境詳細步驟總結乾貨

一、原始碼編譯安裝(C++版) 1.安裝一系列依賴項: sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev