最近開始看Tair的源碼實現,Tair的通信使用的是淘寶的開源的網絡庫tbnet實現。具體來說是依靠tbnet::Transport類型實現,其源代碼路徑如下:
http://code.taobao.org/svn/tb-common-utils/trunk/tbnet/src
下面介紹其通信流程:
1. 啓動
Transport::start()完成其啓動,主要工作是啓動了兩個線程:_readWriteThread和_timeoutThread. 這兩個線程的實際入口函數式Tranport::run(), 下面是Transport::run的實現:
點擊(此處)摺疊或打開
- void Transport::run(tbsys::CThread
*thread, void
*arg)
{
- if (thread
==
&_timeoutThread)
{
- timeoutLoop();
- } else
{
- eventLoop((SocketEvent*)arg);
- }
- }
1. 讀寫線程使用epoll實現,在Transport中存在一個EPollSocketEvent _socketEvent 成員變量, arg傳入的是這個成員變量的指針,EPollSocketEvent是epoll個操作的封裝,在EPollSocketEvent的構造函數中會調用epoll_create初始化epoll。
2. eventLoop的實現步驟如下:
a. 調用socketEvent->getEvents() 取得發生的事件並放入到ioevents數組中
i. 調用epoll_wait等待讀寫事件;
ii. 每個事件的events[i].data.ptr存放有事件對應的IOComonet(socket 封裝),可以用來處理讀寫事件;
b. 對於讀寫事件,分別調用ioc->handleReadEvent()和ioc->handleWriteEvent()處理;
B. timeout線程
1. 主要用於檢查通信的socket是否超過一定時常沒有使用,對於TCPComponent(封裝通信socket),如果15分鐘沒有使用,則斷開連接;
2. 監聽
通過調用Transport::listen()完成監聽, 主要完成以下步驟:
a. 創建TCPAcceptor,繼承於IOComonet(socket 封裝),並啓動異步監聽;
b. 調用addComponent(acceptor, true, false);
i. 創建epoll_event ev,設置ev.data.ptr = socket->getIOComponent(),用來處理讀寫事件的IOComponentsocket 封裝)
ii. 調用epoll_ctl(_iepfd,EPOLL_CTL_ADD,socket->getSocketHandle(),&ev)註冊監聽socket上的讀取事件;
c. 當客戶端有connect請求過來的時候會觸發監聽socket上的讀取事件,TCPAcceptor::handleReadEvent()會被調用。
3. 接受客戶端的連接請求
系統在TCPAcceptor::handleReadEvent()中接受客戶端的連接請求,主要步驟如下:
a. socket = ((ServerSocket*)_socket)->accept() 接受連接請求並得到通信socket;
b. 創建TCPComponent封裝通信socket;
c. 調用addComponent(component, true, false) 註冊當前socket的讀取事件。
4. 數據通信
A. 數據讀取
數據通信由通信socket完成,該socket在epoll中註冊,當有數據需要讀取的時候會觸發讀取事件並調用TCPComponent::handleReadEvent()處理。
B. 數據發送
當有數據需要發送時Connection::postPacket()函數, 這個函數中會調用_iocomponent->enableWrite(true),註冊寫入事件,並調用TCPComponent::handleWriteEvent()處理。