Apache Traffic Server插件開發(fā)手記(二)

目錄

一轩娶、原理分析

二、主要函數(shù)

三坎怪、代碼實(shí)現(xiàn)

四罢坝、測試過程

-----------------------------------------------------------------------------------

一、原理分析

ATS是做服務(wù)器最好的選擇搅窿,服務(wù)器最重要的兩件事就是接收處理用戶的請求并發(fā)送反饋的信息給用戶嘁酿。這個(gè)帖子的目的在于介紹幾個(gè)接收、發(fā)送數(shù)據(jù)的處理函數(shù)的使用男应。

先來看下闹司,整體的結(jié)構(gòu)

裝逼的功能:我希望在ATS的基礎(chǔ)上,開發(fā)一個(gè)插件游桩,這個(gè)插件能夠接收用戶的連接請求盹憎,同時(shí)能發(fā)送數(shù)據(jù)給用戶。

實(shí)際的功能:這不就是個(gè)Socket的發(fā)送铐刘、接收功能嗎陪每。。镰吵。

socket歸socket疤祭,不同的是ATS如何利用Socket+Event+Continuations這三種機(jī)制實(shí)現(xiàn)這一最基本的功能盼产。


二、主要函數(shù)

ATS中插件是運(yùn)行在continuations(協(xié)程)的機(jī)制上的谓传,可以說一個(gè)插件就是一個(gè)或多個(gè)continuations組成的蜈项,所以先介紹的兩個(gè)函數(shù)是continuations的創(chuàng)建與銷毀

TSCont TSContCreate(TSEventFunc funcp, TSMutex mutexp);

###funcp是指continuations用來處理事件的主要函數(shù),創(chuàng)建函數(shù)是用來創(chuàng)建并綁定事件處理函數(shù)

void TSContDestroy(TSCont contp);

第二续挟,之前介紹到,數(shù)據(jù)會(huì)隨著continuations的掛起而保存侥衬,有點(diǎn)像中斷诗祸,接下來的這個(gè)函數(shù)能將要保存的數(shù)據(jù)與協(xié)程綁定起來

void TSContDataSet(TSCont contp, void *data);

###void *data即要保存的數(shù)據(jù),可以是類轴总、結(jié)構(gòu)體等等直颅。

void *TSContDataGet(TSCont contp);

###獲取dataset所保存的數(shù)據(jù)

TSAction TSNetAccept(TSCont contp, int port, int domain, int accept_threads);

###綁定并監(jiān)聽端口,第3個(gè)參數(shù)domain的值可參考socket的值怀樟,一般是設(shè)置AF_INET功偿,最后一個(gè)是回調(diào)函數(shù)的線程ID,可設(shè)置回調(diào)可不設(shè)置

int TSContCall(TSCont contp, TSEvent event, void *edata);

###回調(diào)與cont綁定的eventhandler函數(shù)往堡,第二個(gè)參數(shù)為事件的代號

第三械荷,接收有關(guān)數(shù)據(jù)的讀、寫操作的函數(shù)


當(dāng)請求接入后虑灰,TSNetAccept的data是一個(gè)TSVconn的類吨瞎,也就是通過這個(gè)類在兩者之間建立聯(lián)系

數(shù)據(jù)的讀取(寫入)需要通過IObuffer穆咐、IOBufferReader颤诀、TSIOBufferBlock相互配合才能將數(shù)據(jù)從buffer中讀茸中瘛(寫入)出來。

主要的幾個(gè)函數(shù)(以讀取函數(shù)為例)

TSVIO TSVConnRead(TSVConn connp, TSCont contp, TSIOBuffer bufp, int64_t nbytes);

###將連接發(fā)送給協(xié)程數(shù)據(jù)關(guān)聯(lián)至IOBuffer中崖叫,同時(shí)nbytes設(shè)置IObuffer的空間大小遗淳,當(dāng)有數(shù)據(jù)寫入時(shí),觸發(fā)該協(xié)程的回調(diào)事件函數(shù)心傀。

const char *TSIOBufferBlockReadStart(TSIOBufferBlock blockp, TSIOBufferReader readerp, int64_t *avail);

###將數(shù)據(jù)讀出屈暗,avail表示用于存放讀書數(shù)據(jù)字節(jié)數(shù)的地址

TSIOBufferBlock TSIOBufferBlockNext(TSIOBufferBlock blockp);

###每次讀取的數(shù)據(jù)有限,通過block的方式多次讀取剧包,這里的block相當(dāng)于指針一樣恐锦,隨著讀取不斷向后移動(dòng)

三、代碼實(shí)現(xiàn)

最后疆液,是通過C++編寫一個(gè)小插件一铅。

首先,我們需要將這個(gè)插件掛載到ATS上堕油,因此需要聲明TSPluginInit函數(shù)潘飘,由于是在CPP的文件里寫的,因此需要聲明用gcc來編譯這個(gè)入口函數(shù)就有如下代碼掉缺,同時(shí)我們再此將插件功能進(jìn)行初始化

extern "C" void TSPluginInit (int argc, const char *argv[]);

void TSPluginInit (int argc, const char *argv[])

{

? ? ????TSPluginRegistrationInfo info;

????????info.plugin_name = "hello-world";

????????info.vendor_name = "MyCompany";

????????info.support_email = "ts-api-support@MyCompany.com";

????????printf("開始運(yùn)行插件\n");

????????if (TSPluginRegister(&info) != TS_SUCCESS) {

????????TSError("注冊失敗2");

????????}

????????helloinit();

}

在初始化函數(shù)中卜录,需要做的有四件事:創(chuàng)建continuations、綁定數(shù)據(jù)存放眶明、綁定事件處理的主函數(shù)艰毒、綁定端口并監(jiān)聽。在這之前搜囱,先創(chuàng)建一用于保存數(shù)據(jù)的機(jī)構(gòu)體(或者類)

typedef struct {

????????TSIOBuffer bufp;

????????TSIOBuffer out_bufp;

????????TSIOBufferReader readerp;

????????TSIOBufferReader out_readerp;

????????TSVConn write_vconnp;

????????TSVConn read_vconnp;

????????TSVIO read_vio;

????????TSVIO write_vio;

} CacheVConnStruct;

于是丑瞧,helloinit、以及主事件處理函數(shù)的代碼為

int helloinit()

{

printf("綁定端口\n");

hello_appcep_cont_=TSContCreate(HelloAccpetHandler, TSMutexCreate());

printf("cont是:%d\n",hello_appcep_cont_);

CacheVConnStruct *cache_vconn = (CacheVConnStruct *)TSmalloc(sizeof(CacheVConnStruct));

TSContDataSet( hello_appcep_cont_, cache_vconn);

TSNetAccept(hello_appcep_cont_, 8899,AF_INET ,1);

}

int HelloAccpetHandler(TSCont cont,TSEvent event,void *data)

{

printf("cont是:%d\n",cont);

printf("回調(diào)連接的事件為:%d\n",event);

switch ((int)event)

{

case TS_EVENT_NET_ACCEPT:

printf("連接正常接入\n");

ReadFromVConn(cont,data);

break;

case TS_EVENT_VCONN_READ_COMPLETE:

printf("讀取完畢\n");

//HandlerReadComplete(cont,data);

break;

case TS_EVENT_VCONN_READ_READY:

printf("buffer尚未讀滿\n");

HandlerReadComplete(cont,data);

}

return 1;

}

接下來蜀肘,需要等待連接接入绊汹,為此我們需要寫個(gè)客戶端的腳本,方便采用python編寫

# -*- coding: utf-8 -*-

import socket

import sys

datatosend="GET / HTTP/1.1\r\nHost: 192.168.31.138:8899\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n"

TCP_IP = '192.168.31.138'

TCP_PORT = 8899

ADDR=(TCP_IP,TCP_PORT)

print ADDR

try:

????#create an AF_INET, STREAM socket (TCP)

????s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

except socket.error, msg:

????print 'Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]

????sys.exit();

????#s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

????print 'Socket Created'

try:

????s.connect((TCP_IP,TCP_PORT))

except socket.error , msg:

????print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]

????sys.exit()

s.send(datatosend)

i=i+1

當(dāng)客戶端連接服務(wù)器后扮宠,ATS會(huì)觸發(fā)事件函數(shù)202表接受了請求西乖,建立連接,這個(gè)時(shí)候就綁定IOBuffer并聲明buffer的空間坛增,同時(shí)我直接發(fā)送給對端一個(gè)鏈接的信號获雕,代碼如下:

void ReadFromVConn(TSCont cont,void *data)

{

CacheVConnStruct *recv_sm=(CacheVConnStruct*)TSContDataGet( cont);

recv_sm->bufp =TSIOBufferCreate();

recv_sm->read_vconnp=(TSVConn)data;

TSVConnRead((TSVConn)data, cont, recv_sm->bufp, 500);

TSVConn input_request=(TSVConn)data;

printf("%s\n",input_request);

TSIOBuffer input_bufp=TSIOBufferCreate();

TSIOBufferReader input_bufp_reader=TSIOBufferReaderAlloc(input_bufp);

TSIOBuffer output_bufp=TSIOBufferCreate();

TSIOBufferReader output_bufp_reader=TSIOBufferReaderAlloc(output_bufp);

/////////發(fā)送數(shù)據(jù)部分

TSIOBufferBlock blockp;

char *ptr_block;

int64_t avail;

blockp? ? = TSIOBufferStart(output_bufp);

ptr_block = TSIOBufferBlockWriteStart(blockp, &avail);

memcpy(ptr_block, "i love ats", 11);

TSIOBufferProduce(output_bufp, 11);

TSVIO write_io=TSVConnWrite(input_request, cont,output_bufp_reader, 11);

}

當(dāng)IOBuffer中有數(shù)據(jù)的時(shí)候就會(huì)觸發(fā)事件102或者103,102表示發(fā)送過來的數(shù)據(jù)尚未填滿buffer,103表示buffer已經(jīng)滿了轿偎。那么將數(shù)據(jù)讀出的代碼如下:

int HandlerReadComplete(TSCont cont,void *data)

{

CacheVConnStruct *cache_vconn=(CacheVConnStruct*)TSContDataGet( cont);

cache_vconn->readerp=TSIOBufferReaderAlloc(cache_vconn->bufp);

int avail=TSIOBufferReaderAvail(cache_vconn->readerp);

printf("共有%d個(gè)數(shù)據(jù)\n",avail);

if(avail>0)

{

string str;

const char *buffer_temp=new char[1024];

int consumed=0;

TSIOBufferBlock block = TSIOBufferReaderStart(cache_vconn->readerp);

int64_t data_len;

str.reserve(avail + 1);

while (block)

{

buffer_temp=TSIOBufferBlockReadStart( block, cache_vconn->readerp, &data_len);

str.append(buffer_temp,data_len);

consumed+=data_len;

block=TSIOBufferBlockNext( block);

}

printf("\n%s\n",str.c_str());

}

}

四典鸡、測試過程

為了測試這個(gè)插件的過程,編寫一個(gè)腳本坏晦,自動(dòng)編譯萝玷、自動(dòng)重啟嫁乘、自動(dòng)刪除日志、自動(dòng)啟動(dòng)測試客戶端球碉、自動(dòng)關(guān)閉ATS蜓斧,命令如下

/usr/local/ats/bin/tsxs -lpthread -o hello.so -c hello.cpp

sudo /usr/local/ats/bin/tsxs -o hello.so -i

sudo rm -f /usr/local/ats/var/log/trafficserver/*

sudo /usr/local/ats/bin/trafficserver restart

sleep 3s

python /home/carl/httpsend.py &

sleep 9s

sudo /usr/local/ats/bin/trafficserver stop

sleep 1s

可以看到,客戶端啟動(dòng)后睁冬,接收到了ATS發(fā)送過來的數(shù)據(jù)


同時(shí)查看ATS的日志挎春,可以看到對應(yīng)事件回調(diào)的過程


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市豆拨,隨后出現(xiàn)的幾起案子直奋,更是在濱河造成了極大的恐慌,老刑警劉巖施禾,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脚线,死亡現(xiàn)場離奇詭異,居然都是意外死亡弥搞,警方通過查閱死者的電腦和手機(jī)邮绿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攀例,“玉大人船逮,你說我怎么就攤上這事≡撩” “怎么了挖胃?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梆惯。 經(jīng)常有香客問我冠骄,道長,這世上最難降的妖魔是什么加袋? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮抱既,結(jié)果婚禮上职烧,老公的妹妹穿的比我還像新娘。我一直安慰自己防泵,他們只是感情好蚀之,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捷泞,像睡著了一般足删。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锁右,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機(jī)與錄音虑啤,去河邊找鬼馒闷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛痪署,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兄旬,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼狼犯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了领铐?” 一聲冷哼從身側(cè)響起悯森,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绪撵,沒想到半個(gè)月后瓢姻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡莲兢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年汹来,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片改艇。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡收班,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谒兄,到底是詐尸還是另有隱情摔桦,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布承疲,位于F島的核電站邻耕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏燕鸽。R本人自食惡果不足惜兄世,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望啊研。 院中可真熱鬧御滩,春花似錦、人聲如沸党远。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沟娱。三九已至氛驮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間济似,已是汗流浹背矫废。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工盏缤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磷脯。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓蛾找,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赵誓。 傳聞我的和親對象是個(gè)殘疾皇子打毛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

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

  • 第1章 第一個(gè)C程序第2章 C語言基礎(chǔ)第3章 變量和數(shù)據(jù)類型第4章 順序結(jié)構(gòu)程序設(shè)計(jì)第5章 條件結(jié)構(gòu)程序設(shè)計(jì)第6章...
    小獅子365閱讀 10,675評論 3 71
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,990評論 0 7
  • 多線程幻枉、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場景诡蜓。SDWebImage的原...
    LZM輪回閱讀 2,009評論 0 12
  • C語言中內(nèi)存分配 在任何程序設(shè)計(jì)環(huán)境及語言中熬甫,內(nèi)存管理都十分重要。在目前的計(jì)算機(jī)系統(tǒng)或嵌入式系統(tǒng)中蔓罚,內(nèi)存資源仍然是...
    一生信仰閱讀 1,165評論 0 2
  • 大綱 一.Socket簡介 二.BSD Socket編程準(zhǔn)備 1.地址 2.端口 3.網(wǎng)絡(luò)字節(jié)序 4.半相關(guān)與全相...
    VD2012閱讀 2,362評論 0 5