boost::asio::io_service與socket(C++)
boost::asio::io_service
io_service類為下面的非同步物件提供核心的I/O操作函式,主要用途還是用於socket程式設計
- boost::asio::ip::tcp::socket
- boost::asio::ip::tcp::acceptor
- boost::asio::ip::udp::socket
- 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的處理流程
- 應用程式呼叫IO物件成員函式執行IO操作;
- IO物件請求io_service的服務;
- io_service 通知作業系統其需要開始一個非同步連線;
- 作業系統指示連線操作完成, io_service從佇列中獲取操作結果;
- 應用程式必須呼叫io_service::run()以便於接收結果;
- 呼叫io_service::run()後,io_service返回一個操作結果,並將其翻譯為error_code,傳遞到事件回撥函式中;
2、然後考察io_service物件
io_service物件主要有兩個方法——post和run:
- post用於釋出io事件,如timer,socket讀寫等,一般由asio框架相應物件呼叫,無需我們顯式呼叫;
- run用於監聽io事件響應,並執行響應回撥,對於非同步io操作需要在程式碼中顯式呼叫;
在非同步io操作中需要我們手動呼叫run函式,基本工作模式如下:
- 等待io事件響應,如果所有io事件響應完成則退出;
- 等待到io事件響應後,執行其對應的回撥;
- 繼續等待下一個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_service與socket(C++)
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
FastSocket(C/C++)、FastSocket.NET(C#)與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#)TCP與UDP通訊流程、Tcplistener和Tcpclient進行通訊、UdpClient進行通訊
1.基於Tcp協議的Socket通訊類似於B/S架構,面向連線,不同的是伺服器端可以向客戶端主動的推送訊息 流程順序。可靠性高 (1)建立一個套接字(Socket) (2)繫結伺服器端IP地址及埠號-伺服器端 (3)利用Listen()方法開啟監聽-伺服器端 (4)利用Accep
共用體union與列舉enum(C++)
一、共用體: 共用體(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