基於Boost.Asio的非同步通訊伺服器設計與開發
boost::asio 通訊伺服器實踐
1.開發環境搭建
1.1.Asio準備
萬事開頭難。對於一個C++的陌生者,編譯一個開源的程式碼並不是一件輕鬆愉快的事情。為使大家在審閱和檢測本程式碼可使用性時沒有必要花費太多時間和精力去編譯Boost::Asio庫,在此把我在編譯boost庫時不愉快的經歷記錄下來,供參考。使用Asio有兩種方式,一種是直接使用Asio庫,到網站:
https://sourceforge.net/projects/asio/files/asio/1.11.0%20%28Development%29/可以下載單獨的Asio庫,目前最新版本為1.11。另一種是使用boost.asio庫,該庫依賴於Boost.System庫,因此需要把下載後的boost原始碼編譯生成相應的庫才能使用。Boost下載地址http://www.boost.org/,目前最新版本為1.61.0. 我下載的版本為1.61.0版本。下載後解壓到E:\boost1610目錄下.
1.2.Qt準備
到Qt官網上下載Qt。我電腦環境是聯想TIANYI 100,4G記憶體,安裝的windwos10筆記本開發,因此下載的是windows版本的Qt5.7版本,安裝比較簡單,按照提示實行“下一步”就可以。
1.3.編譯boost
編譯boost比較麻煩一點,使用Qt自帶的mingw編譯boost步驟如下:
-
配置mingw的系統環境變數PATH。我把QT安裝在C盤下,path值配置為:C:\Qt\Qt5.6.1\Tools\mingw492_32\bin。配置後再命令列中輸入gcc -v 如果配置成功,則顯示為:(配置完後,我試著在命令列中輸入gcc -v,居然提示gcc不是內部命令。然後把電腦重起,再輸入gcc -v,這次顯示成功)。
-
下載boost後,解壓到任意目錄下我的解壓目錄為E:\boost1610;
-
開啟cmd.exe,切換到E:\boost1610目錄下,在命令列中實行bootstrap.bat gcc 生成b2.exe和bjam.exe。Bootstrap.bat 是在Windows下生成自己的bjam.exe 和b2.exe 的指令碼。 在Linux下是bootstrap.sh. Bootstrap.bat gcc命令實行完成後,會在QT解壓的目錄下生成bjam.exe 和b2.exe這兩個檔案.
-
實行b2.exe開始編譯。這個命令會生成一個bin.v2的資料夾,為下一步通過bjam命令提供連結。
-
在命令列視窗下實行bjam "toolset=gcc" install編譯boost原始碼。表示將編譯結果預設儲存到C:\boost目錄下或者指定目錄 bjam.exe “-sTools=mingw” --prefix=d:\boost install 或者 Bjam.exe --prefix=d:\boost toolset=gcc install 來編譯boost。編譯完成後會看到D:\boost資料夾下面有兩個子目錄 include 和lib。 實行這個命令過程非常耗時,慢慢等待。
1.4.使用boost庫
方法一:
1、選擇將這兩個目錄拷貝到mingw目錄下的include和lib目錄中,或者將這兩個目錄的路徑新增到系統路徑中。
2、由於在windows下系統預設的命名方式為libboost-iostreams-mgw44-mt-1-61-0.a 可以改為libboost-iostreams.a. Mt 表示多執行緒,預設。
方法二:
建立Qt專案的時候,都會生成一個XXX.pro的檔案,在該檔案下增加如下程式碼:
#DEFINES+=BOOST_THREAD_USE_LIB
INCLUDEPATH+=E:\Boost\include\boost-1_61
#DEPENDPATH+=E:\Boost\include\boost-1_61
LIBS+=E:\Boost\lib\libboost_system-mgw49-mt-1_61.a
LIBS+=-lpthreadlibwsock32libws2_32
其中最後一行
LIBS+=-lpthreadlibwsock32libws2_32表示要用到windows的完成埠模型下的winsocket庫。
建議使用方法二。
到此,開發環境基本搭建完成。下面開始Boost.Asio設計開發伺服器軟體。
2.Asio通訊伺服器設計
2.1.設計指標
-
跨平臺,一套程式碼在不修改原始碼基礎上可運行於windows和Linux系統;
-
運行於Linux系統上時採用EPOLL模型,運行於Windows上時採用完成埠模型(IOCP),且併發連線量儘可能接近作業系統IO模型提供的理論併發量;
-
能接入任何通過TCP方式連線的客戶端,不受任何具體協議資料包的限制;
-
客戶端傳送資料的時候,要求伺服器應答時,伺服器應答客戶端時間應儘可能小,最低要求小於100毫秒。
-
有效管理伺服器與客戶端連線的生命週期
-
基礎通訊與業務邏輯解耦。
2.2.概要設計
由於跨平臺要求,目前C++適合跨平臺的第三方庫有libevent、asio庫等,我們決定採用asio庫實現。服務程式由通訊服務類、連線類、連線管理類、業務介面模板類等四大類組成。為適應不同的客戶端接入,服務程式不解析任何資料包,只接受客戶端連線和接收客戶端傳送過來的資料。客戶端連線成功後,呼叫聯結器管理物件儲存連線,同時向作業系統投遞非同步讀事件,當客戶端傳送的資料到達伺服器,呼叫聯結器中的讀事件讀取資料,通過業務介面將資料傳遞到業務介面,資料的處理由業務介面進一步處理。客戶端需要伺服器應答的,由業務介面根據客戶端與伺服器端通訊協議格式構造應答資料包後,由聯結器轉發到客戶端。
通訊服務類(TTcpServer):提供基礎的埠監聽監聽,不處理任何業務邏輯,以達到通訊服務類通用的目的。對使用者暴露介面有:
-
SetIpAddress設定監聽的IP地址和埠。
-
SetRecycleSoketTime設定回收掉線的Socket時間間隔。
-
Start啟動方法。啟動方法允許使用者使用單執行緒執行和多執行緒執行,也可以在啟動的同時註冊自己的業務物件。執行緒數量由通訊服務類由執行服務的物理機CPU核心數決定,執行緒數量最大為CPU*2-1.不允許使用者自行開闢執行緒。
-
RegisterBussiness註冊業務物件方法。通過RegisterBussiness方法註冊使用者通過實現業務介面類完成自己的業務邏輯。
聯結器類(TConnector):聯結器類是通訊服務程式的核心,客戶端與服務端連線成功後,會產生一個連線會話通道,該通道我們稱為聯結器,客戶通過聯結器傳送資料到服務端,服務端通過聯結器傳送資料到客戶端。每個聯結器有一個唯一識別符號ConnectorId,通過客戶端唯一識別符號ClientId建立與客戶端的關聯。使用者可以通過查詢聯結器ConnectorId或者ClientId獲取指定的聯結器。聯結器的主要作用就是讀取資料或者下發資料到客戶端,讀取到的資料通過業務介面傳遞給業務處理類,由業務處理類處理資料。
聯結器管理類:聯結器管理類提供儲存聯結器的容器,作為通訊內部管理類,提供聯結器插入到容器、關閉聯結器、刪除聯結器、更改聯結器客戶端ID和聯結器工作引數。
業務介面類:為使用者提供業務處理模板。使用者通過實行業務介面實現自己的業務邏輯。
流程描述:
2.3.詳細設計
曾經用Delphi寫過windows完成埠模型的通訊程式碼,而C++,尚未入門,臨時抱佛腳採用QT編輯器嘗試編寫本案例詳細設計和具體實現,很多命名規則還保留有一些記憶中的Delphi風格。為方便專業級別的C++程式設計師審閱本案例,也因本人不喜歡閱讀那些帶下劃線的程式碼,本詳細設計命名規則解釋如下:
-
所有的類名均用大寫的T字母開頭。
-
public類成員變數統一由大寫的字母開頭。成員變數由兩個單片語成的,每個單詞的首字母均採用大寫。
-
Protect或者Private成員變數m+單詞首字母命名。
-
Public方法名,只有一個單詞的由單詞的第一個字母大寫,其他字母小寫。 由2個單片語成的,每個單詞第一個字母採用大寫,其他用小寫。
-
Protect或者private方法,均採用首個單詞全部小寫,其他單詞的第一個字母大寫。
-
除非不得已,本設計常量定義儘量採用const,不使用巨集定義。
通訊服務類、聯結器類、聯結器管理類、業務邏輯介面,業務邏輯示例TDefeaultBussiness類詳細設計及各物件之間的關係如下圖所示。
2.3.1.通訊伺服器類(TTcpserver)
一、通訊伺服器工作流程:
-
使用TTcpServer::TTcpServer()構造器生成一個TTcpserver物件,如TTcpserver tcpserver; 或者使用帶ip地址和埠號引數的構造器TTcpserver::TTcpServer(string ipAddr,int port)生成一個TTcpServer物件。
-
如果還沒設定監聽的IP地址和埠的,呼叫SetIpAddress設定監聽IP地址和埠。
-
呼叫 RegisterBussiness方法繫結使用者自己實現的業務邏輯物件。
-
呼叫SetRecycleSocketTime方法設定回收斷線的客戶端連線,該步驟可選,如果使用者不呼叫該方法,則預設10分鐘回收一次。
-
呼叫Start方法啟動服務,引數為True時將根據執行的物理伺服器CPU核數產生2*CPU核數-1的執行緒數量執行通訊服務。
-
功能描述:
-
waitAccept方法:使用非同步方式等待遠端客戶端連線,當有連線請求時。如果連線成功,呼叫連線成功回撥函式來儲存連線和投遞非同步讀等待。
-
acceptHandle方法:是waitAccept方法的回撥函式,連線成功後該方法被呼叫,儲存聯結器和投遞非同步讀事件。 如果有異常,則把異常寫到異常日誌中。
-
Start方法:啟動服務。首先呼叫waitAccept等待連線,然後呼叫聯結器管理物件中的OpenTimers方法啟動聯結器回收掉線的聯結器,最後呼叫採用執行緒方式啟動mIoServer.run。
2.3.2.聯結器類
功能描述:
-
DoRead:投遞非同步讀事件等待資料接收,如果讀到客戶端關閉的錯誤程式碼,則關閉連線。
-
ReadHandle:非同步讀事件回撥函式,當讀取到資料後,通過業務介面把資料傳遞到業務處理物件。再次呼叫DoRead投遞讀事件
-
DoWrite:投遞非同步寫事件,由於什麼時候在聯結器上面進行寫操作是由客戶端或者應用協議決定的,投遞寫事件由業務邏輯介面呼叫。
-
writeHandle:非同步寫回調函式,通過該回調函式將寫結果通知給業務層。
2.3.3.聯結器管理類
功能描述:
-
AddConnector方法:為聯結器生成聯結器ID,並把聯結器物件儲存到聯結器容器中。工作流程:
首先中聯結器ID回收站中獲取可以利用的ID,如果沒有,則通過增長方式建立一個ID。
-
其次呼叫容器的插入方法儲存聯結器物件。
-
GetSocket方法:通過聯結器ID或者客戶端ID獲取聯結器。
-
UpdataConnector方法:當客戶端註冊後,更新聯結器的ClientId。由業務介面呼叫。
-
checkConnection方法:定時檢查聯結器容器中是否有掉線的聯結器,並將掉線的聯結器中刪除掉線的聯結器。
原始碼:
/***********************************************
*撰寫時間:2016年8月12日
*C++等級:初級
*作者:
*/
#ifndefTCPSERVER_H
#defineTCPSERVER_H
#include<boost/asio.hpp>
#include<boost/bind.hpp>
#include<boost/thread.hpp>
#include"connector.h"
#include"connectormanager.h"
#include"userbusiness.h"
#include<string>
usingnamespacestd;
classTTcpServer
{
public:
//提供預設的建構函式
TTcpServer();
//提供通過IP和埠構造服務類的建構函式
TTcpServer(conststringipAddress,shortport);
//~TTcpServer(){}
voidSetIpAddress(conststringipAddr,shortport);
voidStart(constboolmultiThread=false);
//結束服務
voidStop();
//註冊業務
voidRegisterBussiness(IBussiness&business);
voidSetRecycleSocketTime(intsecond);
private:
boost::asio::io_servicemIoServer;
boost::asio::ip::tcp::endpointmEndpoint;
boost::asio::ip::tcp::acceptormAcceptor;
TConnectorManagermConnectorManager;
//執行緒組,儲存的是執行緒地址,本例不適應,學習參考
boost::thread_groupmWorkers;
//執行緒組,用智慧指標儲存,自動化管理
std::vector<boost::shared_ptr<boost::thread>>mThreads;
//業務介面
IBussiness*pmBussiness;
intmRecycleTime;
//連線處理器
voidacceptHandle(boost::shared_ptr<TConnector>pConnection,constboost::system::error_code&error);
//監聽埠,等待連線
voidwaitAccept();
//建立執行緒池
voidopenThreadPool();
};
#endif//TCPSERVER_H
#include"boost/enable_shared_from_this.hpp"
//#include<boost/thread.hpp>
#include<boost/thread/thread.hpp>
#include"tcpserver.h"
#include"userbusiness.h"
TTcpServer::TTcpServer()
:mAcceptor(mIoServer),
mConnectorManager(mIoServer),
mRecycleTime(60)
{
}
TTcpServer::TTcpServer(conststringipAddress,shortport)
:mEndpoint(boost::asio::ip::address_v4::from_string(ipAddress),port),
mAcceptor(mIoServer,mEndpoint),mConnectorManager(mIoServer)
{
}
//等待連線
voidTTcpServer::waitAccept()
{
//構造一個虛擬的連線物件
boost::shared_ptr<TConnector>pConnection(newTConnector(mIoServer,pmBussiness));
//等待客戶端連線,連線成功將連線資訊儲存到pConnection中
mAcceptor.async_accept(pConnection->GetSocket(),
boost::bind(&TTcpServer::acceptHandle,this,pConnection,boost::asio::placeholders::error()));
}
//連線事件回撥函式
voidTTcpServer::acceptHandle(boost::shared_ptr<TConnector>pConnection,constboost::system::error_code&err)
{
if(!err)
{
try
{
//再次監聽連線
waitAccept();
//投遞讀準備
if(NULL!=pConnection)
{
//pConnection->InitSocket();
pConnection->DoRead();
//本次連線儲存到聯結器容器中
mConnectorManager.AddConnector(pConnection);
}
}
catch(std::exception&e)
{
//寫異常日誌
}
catch(...)
{
相關推薦
基於Boost.Asio的非同步通訊伺服器設計與開發
boost::asio 通訊伺服器實踐 1.開發環境搭建 1.1.Asio準備 萬事開頭難。對於一個C++的陌生者,編譯一個開源的程式碼並不是一件輕鬆愉快的事情。為使大家在審閱和檢測本程式碼可使用性時沒有必要花費太多時間和精力去編譯Boost::Asio
【棋牌遊戲】JAVA伺服器設計與開發(一)
####開篇語 大概在16年時候,新型房卡模式開啟棋牌遊戲新里程,整個棋牌行業迅速改變模式,出現近兩三年激烈的競爭景象,據統計全國大大小小棋牌遊戲公司,專職棋牌公司近兩萬多家,這都不算後起大大小小遊戲公司加緊棋牌研發行列。新型棋牌模式有一個很明顯的特點,那就是地
boost asio 非同步實現tcp通訊
一、前言 boost asio可算是一個簡單易用,功能又強大可跨平臺的C++通訊庫,效率也表現的不錯,linux環境是epoll實現的,而windows環境是iocp實現的。而tcp通訊是專案當中經常用到通訊方式之一,實現的方法有各式各樣,因此總結一套適用於自己專案的方法是
boost::asio 非同步主動連線多個伺服器
#include "ATC.hpp" namespace PWRD{ namespace Network{ //-------------------------------------------------------------------------
基於SSH2的新聞資訊管理平臺的設計與開發——論文隨筆
一、基本資訊 標題:基於SSH2的新聞資訊管理平臺的設計與開發 時間:2017-03 出版源:青島大學 領域分類:系統設計與架構 二、研究背景 問題定義:如何人性化、個性化的為不同使用者提供不同的特定的新聞以滿足使用者需求 難點:使用者的喜好各不同,如何精確的制定使用者畫像 相關工作:使用者可以通過分類
基於SSH2的新聞信息管理平臺的設計與開發——論文隨筆
百度 完成 得到 技術分享 alt 搜索功能 方法 ron 身份驗證 一、基本信息 標題:基於SSH2的新聞信息管理平臺的設計與開發 時間:2017-03 出版源:青島大學 領域分類:系統設計與架構 二、研究背景 問題定義:如何人性化、個性化的為不同用戶提供不同的特定的新聞
文獻綜述三:基於JSP的商品資訊管理系統設計與開發
一、基本資訊 標題:基於JSP的商品資訊管理系統設計與開發 時間:2015 出版源:Computer Knowledge and Technology 檔案分類:jsp技術的系統開發 二、研究背景 通過了解公司產品人工現狀的一些管理方面的現狀和要求,運用計算機技術開發的商品資訊管理系統,能
基於android的天氣預報的設計與實現
目錄 應用開發技術及開發平臺介紹 應用需求分析 應用功能設計及其描述 應用UI展示 ①開發技術: 本系統是採用面向物件的軟體開發方法,基於Android studio開發平臺,以Android作為本系統的開發語言實現音樂播放器預定的需求功能。 ②平臺介紹 硬體平臺
[原始碼和文件分享]基於C++的庫存管理系統設計與實現
一 需求分析 1.1 總體要求 運用面向物件程式設計知識,利用C++語言設計和實現一個“庫存管理系統設計”,主要完成對商品的銷售、統計和簡單管理。在實現過程中,需利用面向物件程式設計理論的基礎知識,充分體現出C++語言關於類、繼承和封裝等核心概念,每一個類應包含資料成員和成員函式。 1.
[原始碼和文件分享]基於C++的通訊錄系統的設計與實現
一 需求分析 通訊錄系統可幫助使用者管理歸納通訊錄名單,達到新增,刪除,修改,儲存等需求。 二 系統設計 2.1 功能模組設計 通訊錄主要功能為:新增通訊錄成員,修改成員,刪除成員,按需求搜尋檢視成員,儲存為文件。 如下圖所示: 系統各模組的功能具體描述為:
[原始碼和文件分享]基於C++的學生生活系統設計與實現
一 需求分析 需要設計並實現如下場景:在那山的那邊,湖的那邊,有一所學校,學校裡有一幢宿舍樓,宿舍樓有若干層,每一層有若干房間 ,一群學生快樂地生活在這裡。他們每天可做的事情有: 換宿舍,從一個房間搬到另一個房間 退學,亦即搬出宿舍樓 入學,亦即搬入宿舍樓
[原始碼和文件分享]基於C#語言的計算器的設計與實現
一 需求分析 利用c#語言實現一個計算器程式,包括普通計算器模式、科學計算器模式;實現實數(包括正數、負數、0)的加、減、乘、除、平方等基本遠算,並實現非負數的開方運算。 二 程式設計與實現 首先設計主窗體,包括兩個TextBox用來顯示資料,使用資料繫結實現,在Model中實現INot
基於WEB的教職工健康檔案管理系統,java設計與開發
**基於WEB的教職工健康檔案管理系統,java設計與開發** 基於WEB的教職工健康檔案管理系統mysql資料庫建立語句 基於WEB的教職工健康檔案管理系統oracle資料庫建立語句 基於WEB的教職工健康檔案管理系統sqlserver資料庫建立語句 基於WEB的
基於SSH的個人網站的設計與實現
**基於SSH的個人網站的設計與實現** 基於SSH的個人網站的設計與實現mysql資料庫建立語句 基於SSH的個人網站的設計與實現oracle資料庫建立語句 基於SSH的個人網站的設計與實現sqlserver資料庫建立語句 基於SSH的個人網站的設計與實現spri
基於boost asio實現的ssl socket框架
情景分析 現已存在一個可用穩定的非同步客戶端類http_client_base,該類基於boost asio實現了連線伺服器,傳送請求,獲取響應和解析http資料等操作,該類的大致實現框架如下 1class http_client_base 2{ 3public: 4
[原始碼和文件分享]基於QT的考試管理系統設計與實現
一、專案概要 1.1 專案名稱 考試管理系統 1.2 專案目標 培養快速學習新的知識,解決問題的能力 規劃專案的整體功能以及相關需求分析,並設計出合理的資料庫,並熟悉整個試題系統的開發流程。 1.3 軟體概要 開發一個考試管理系統,考生可以進行練習,
基於JSP的房屋出租管理系統系統設計,java設計與開發
**基於JSP的房屋出租管理系統系統設計,java設計與開發** 基於JSP的房屋出租管理系統系統設計mysql資料庫建立語句 基於JSP的房屋出租管理系統系統設計oracle資料庫建立語句 基於JSP的房屋出租管理系統系統設計sqlserver資料庫建立語句 基於
基於Bootstrap框架的臨床資料管理系統的設計與開發
基於Bootstrap框架的臨床資料管理系統的設計與開發 2018年11月10日 目 錄 第一章緒論
boost asio非同步讀寫網路聊天室【官方示例】
// // chat_message.hpp // ~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distri
AndroidAsync :基於nio的非同步通訊庫
AndroidAsync 是一個基於nio的非同步socket ,http(客戶端伺服器端),websocket,socket.io庫,AndroidAsync 是一個底層的網路協議庫,如果你想要一個容易使用,高階的,http請求庫,請使用Ion(它是基於Android