(3)基礎(chǔ)的socket服務(wù)器開發(fā)(Reactor部分)【Lars-基于C++負(fù)載均衡遠(yuǎn)程服務(wù)器調(diào)度系統(tǒng)教程】

【Lars教程目錄】

Lars源代碼
https://github.com/aceld/Lars


【Lars系統(tǒng)概述】
第1章-概述
第2章-項(xiàng)目目錄構(gòu)建


【Lars系統(tǒng)之Reactor模型服務(wù)器框架模塊】
第1章-項(xiàng)目結(jié)構(gòu)與V0.1雛形
第2章-內(nèi)存管理與Buffer封裝
第3章-事件觸發(fā)EventLoop
第4章-鏈接與消息封裝
第5章-Client客戶端模型
第6章-連接管理及限制
第7章-消息業(yè)務(wù)路由分發(fā)機(jī)制
第8章-鏈接創(chuàng)建/銷毀Hook機(jī)制
第9章-消息任務(wù)隊(duì)列與線程池
第10章-配置文件讀寫功能
第11章-udp服務(wù)與客戶端
第12章-數(shù)據(jù)傳輸協(xié)議protocol buffer
第13章-QPS性能測試
第14章-異步消息任務(wù)機(jī)制
第15章-鏈接屬性設(shè)置功能


【Lars系統(tǒng)之DNSService模塊】
第1章-Lars-dns簡介
第2章-數(shù)據(jù)庫創(chuàng)建
第3章-項(xiàng)目目錄結(jié)構(gòu)及環(huán)境構(gòu)建
第4章-Route結(jié)構(gòu)的定義
第5章-獲取Route信息
第6章-Route訂閱模式
第7章-Backend Thread實(shí)時(shí)監(jiān)控


【Lars系統(tǒng)之Report Service模塊】
第1章-項(xiàng)目概述-數(shù)據(jù)表及proto3協(xié)議定義
第2章-獲取report上報(bào)數(shù)據(jù)
第3章-存儲線程池及消息隊(duì)列


【Lars系統(tǒng)之LoadBalance Agent模塊】
第1章-項(xiàng)目概述及構(gòu)建
第2章-主模塊業(yè)務(wù)結(jié)構(gòu)搭建
第3章-Report與Dns Client設(shè)計(jì)與實(shí)現(xiàn)
第4章-負(fù)載均衡模塊基礎(chǔ)設(shè)計(jì)
第5章-負(fù)載均衡獲取Host主機(jī)信息API
第6章-負(fù)載均衡上報(bào)Host主機(jī)信息API
第7章-過期窗口清理與過載超時(shí)(V0.5)
第8章-定期拉取最新路由信息(V0.6)
第9章-負(fù)載均衡獲取Route信息API(0.7)
第10章-API初始化接口(V0.8)
第11章-Lars Agent性能測試工具
第12章- Lars啟動(dòng)工具腳本


1) 框架結(jié)構(gòu)

2-Lars-reactor.png

2) Lars Reactor V0.1開發(fā)

? 我們首先先完成一個(gè)最基本的服務(wù)器開發(fā)模型郭卫,封裝一個(gè)tcp_server類调违。

lars_reactor/include/tcp_server.h

#pragma once

#include <netinet/in.h>


class tcp_server
{ 
public: 
    //server的構(gòu)造函數(shù)
    tcp_server(const char *ip, uint16_t port); 

    //開始提供創(chuàng)建鏈接服務(wù)
    void do_accept();

    //鏈接對象釋放的析構(gòu)
    ~tcp_server();

private: 
    int _sockfd; //套接字
    struct sockaddr_in _connaddr; //客戶端鏈接地址
    socklen_t _addrlen; //客戶端鏈接地址長度
}; 

? 在tcp_server.cpp中完成基本的功能實(shí)現(xiàn)胁后,我們在構(gòu)造函數(shù)里將基本的socket創(chuàng)建服務(wù)器編程寫完偿荷,然后提供一個(gè)阻塞的do_accept()方法才菠。

lars_reactor/src/tcp_server.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>

#include "tcp_server.h"


//server的構(gòu)造函數(shù)
tcp_server::tcp_server(const char *ip, uint16_t port)
{
    bzero(&_connaddr, sizeof(_connaddr));
    
    //忽略一些信號 SIGHUP, SIGPIPE
    //SIGPIPE:如果客戶端關(guān)閉蹦锋,服務(wù)端再次write就會(huì)產(chǎn)生
    //SIGHUP:如果terminal關(guān)閉忆谓,會(huì)給當(dāng)前進(jìn)程發(fā)送該信號
    if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
        fprintf(stderr, "signal ignore SIGHUP\n");
    }
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
        fprintf(stderr, "signal ignore SIGPIPE\n");
    }

    //1. 創(chuàng)建socket
    _sockfd = socket(AF_INET, SOCK_STREAM /*| SOCK_NONBLOCK*/ | SOCK_CLOEXEC, IPPROTO_TCP);
    if (_sockfd == -1) {
        fprintf(stderr, "tcp_server::socket()\n");
        exit(1);
    }

    //2 初始化地址
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    inet_aton(ip, &server_addr.sin_addr);
    server_addr.sin_port = htons(port);

    //2-1可以多次監(jiān)聽夜赵,設(shè)置REUSE屬性
    int op = 1;
    if (setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op)) < 0) {
        fprintf(stderr, "setsocketopt SO_REUSEADDR\n");
    }

    //3 綁定端口
    if (bind(_sockfd, (const struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        fprintf(stderr, "bind error\n");
        exit(1);
    }

    //4 監(jiān)聽ip端口
    if (listen(_sockfd, 500) == -1) {
        fprintf(stderr, "listen error\n");
        exit(1);
    }
}

//開始提供創(chuàng)建鏈接服務(wù)
void tcp_server::do_accept()
{
    int connfd;    
    while(true) {
        //accept與客戶端創(chuàng)建鏈接
        printf("begin accept\n");
        connfd = accept(_sockfd, (struct sockaddr*)&_connaddr, &_addrlen);
        if (connfd == -1) {
            if (errno == EINTR) {
                fprintf(stderr, "accept errno=EINTR\n");
                continue;
            }
            else if (errno == EMFILE) {
                //建立鏈接過多,資源不夠
                fprintf(stderr, "accept errno=EMFILE\n");
            }
            else if (errno == EAGAIN) {
                fprintf(stderr, "accept errno=EAGAIN\n");
                break;
            }
            else {
                fprintf(stderr, "accept error");
                exit(1);
            }
        }
        else {
            //accept succ!
            //TODO 添加心跳機(jī)制
            
            //TODO 消息隊(duì)列機(jī)制
            
            int writed;
            char *data = "hello Lars\n";
            do {
                writed = write(connfd, data, strlen(data)+1);
            } while (writed == -1 && errno == EINTR);

            if (writed > 0) {
                //succ
                printf("write succ!\n");
            }
            if (writed == -1 && errno == EAGAIN) {
                writed = 0; //不是錯(cuò)誤排作,僅返回0表示此時(shí)不可繼續(xù)寫
            }
        }
    }
}

//鏈接對象釋放的析構(gòu)
tcp_server::~tcp_server()
{
    close(_sockfd);
}

? 好了牵啦,現(xiàn)在回到lars_reactor目錄下進(jìn)行編譯棍丐。

$~/Lars/lars_reactor/
$make

lib下仍劈,得到了庫文件。

接下來兴蒸,做一下測試衫生,寫一個(gè)簡單的服務(wù)器應(yīng)用.

$cd ~/Lars/lars_reactor/example
$mkdir lars_reactor_0.1
$cd lars_reactor_0.1

lars_reactor/example/lars_reactor_0.1/Makefile

CXX=g++
CFLAGS=-g -O2 -Wall -fPIC -Wno-deprecated 

INC=-I../../include
LIB=-L../../lib -llreactor 
OBJS = $(addsuffix .o, $(basename $(wildcard *.cc)))

all:
    $(CXX) -o lars_reactor $(CFLAGS)  lars_reactor.cpp $(INC) $(LIB)

clean:
    -rm -f *.o lars_reactor

lars_reactor/example/lars_reactor_0.1/lars_reactor.cpp

#include "tcp_server.h"

int main() {

    tcp_server server("127.0.0.1", 7777);
    server.do_accept();

    return 0;
}

? 接下來裳瘪,我們make進(jìn)行編譯,編譯的時(shí)候會(huì)指定鏈接我們剛才生成的liblreactor.a庫罪针。

服務(wù)端:

$ ./lars_reactor 
begin accept

客戶端:

$nc 127.0.0.1 7777
hello Lars

得到了服務(wù)器返回的結(jié)果彭羹,那么我們最開始的0.1版本就已經(jīng)搭建完了,但是實(shí)際上這并不是一個(gè)并發(fā)服務(wù)器泪酱,萬里長征才剛剛開始而已派殷。


關(guān)于作者:

作者:Aceld(劉丹冰)

mail: danbing.at@gmail.com
github: https://github.com/aceld
原創(chuàng)書籍gitbook: http://legacy.gitbook.com/@aceld

原創(chuàng)聲明:未經(jīng)作者允許請勿轉(zhuǎn)載, 如果轉(zhuǎn)載請注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市墓阀,隨后出現(xiàn)的幾起案子毡惜,更是在濱河造成了極大的恐慌,老刑警劉巖斯撮,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件经伙,死亡現(xiàn)場離奇詭異,居然都是意外死亡勿锅,警方通過查閱死者的電腦和手機(jī)帕膜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進(jìn)店門枣氧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人垮刹,你說我怎么就攤上這事作瞄。” “怎么了危纫?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵宗挥,是天一觀的道長。 經(jīng)常有香客問我种蝶,道長契耿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任螃征,我火速辦了婚禮搪桂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盯滚。我一直安慰自己踢械,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布魄藕。 她就那樣靜靜地躺著内列,像睡著了一般。 火紅的嫁衣襯著肌膚如雪背率。 梳的紋絲不亂的頭發(fā)上话瞧,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天,我揣著相機(jī)與錄音寝姿,去河邊找鬼交排。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饵筑,可吹牛的內(nèi)容都是我干的埃篓。 我是一名探鬼主播,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼根资,長吁一口氣:“原來是場噩夢啊……” “哼架专!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嫂冻,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤胶征,失蹤者是張志新(化名)和其女友劉穎塞椎,沒想到半個(gè)月后桨仿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡案狠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年服傍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钱雷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,697評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吹零,死狀恐怖罩抗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灿椅,我是刑警寧澤套蒂,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站茫蛹,受9級特大地震影響操刀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婴洼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一骨坑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柬采,春花似錦欢唾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肩刃,卻和暖如春亡脸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背树酪。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工浅碾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人续语。 一個(gè)月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓垂谢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親疮茄。 傳聞我的和親對象是個(gè)殘疾皇子滥朱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容