主要分析gloox的connect模塊,涉及的文件:
connectionbase.h
connectiondatahander.h
connectionhandler.h
connectiontcpbase.h (connectiontcpbase.cpp)
connectiontcpclient.h (connectiontcpclient.cpp)
connectiontcpserver.h (connectiontcpserver.cpp)
1. ConnectionBase抽象連接類,表示一個(gè)socket連接。3個(gè)數(shù)據(jù)成員:
server和ip - 需要連接到的目標(biāo)地址和端口(在ConnectionTcpServer是要綁定的本地地址)
connectionState - 連接的當(dāng)前狀態(tài) (一個(gè)三種狀態(tài)disconnected | connecting | connected)
connectionDataHandler - 處理三類ConnectionBase中的三類事件 ( 數(shù)據(jù)接收 | 連接建立 | 連接斷開 )
5個(gè)主要方法:
connect - 建立一個(gè)socket連接
disconnect - 斷開一個(gè)socket連接
send - 發(fā)送數(shù)據(jù),該方法直到要發(fā)送的數(shù)據(jù)全部發(fā)送完畢才返回
recv( int timeout ) - 接收數(shù)據(jù),接收到數(shù)據(jù)或者timeout返回
receive - 把connection設(shè)置成"接收模式",也就是循環(huán)的調(diào)用recv接收數(shù)據(jù),直到連接斷開該方法返回,
該方法保證這個(gè)連接可以循環(huán)的接收數(shù)據(jù).
注意: recv和receive的區(qū)別。
2. ConnectionDataHandler處理繼承自ConnectionBase的對(duì)象的事件handlerReceivedData - 接收到數(shù)據(jù)
handlerConnect - 一個(gè)原始的套接字連接建立
handlerDisconnect - 一個(gè)原始的套接字連接斷開
3. ConnectionTcpBase一個(gè)基本的TCP連接,繼承自ConnectionBase數(shù)據(jù)成員
bool cancel - 表示連接是否應(yīng)該斷開,默認(rèn)為true. (true表示連接斷開)
函數(shù)disconnect也就是僅僅設(shè)置cancel為true.
在函數(shù)receive循環(huán)接收數(shù)據(jù)的邏輯中會(huì)檢測cancel,如果為true,則表示連接斷開,則返回,退出"接收模式"
int bufSize - buf的大小,默認(rèn)是1024
char* buf - 緩沖區(qū),大小事bufSize + 1 (在ConnectionTcpBase中并沒有用到這個(gè)緩沖區(qū),供上層使用E.g. ConnectionTcpClient的recv來接收數(shù)據(jù))
實(shí)現(xiàn)的主要方法:
send - 發(fā)送數(shù)據(jù)
receive - "循環(huán)"接收數(shù)據(jù)
dataAvailable( int timeout ) - 一個(gè)私有方法,作用是測試socket上目前是否有數(shù)據(jù)可讀,如果有返回true. 可以供recv調(diào)用. 避免了阻塞的調(diào)用原始套接字方法::receive或者::accept.
4. ConnectionTcpClient實(shí)現(xiàn)一個(gè)基本的TCP連接,繼承自ConnectionTcpBase實(shí)現(xiàn)的主要方法
connect - 連接到目標(biāo)地址,如果成功,則調(diào)用handler->handlerConnect,失敗則調(diào)用handler->handlerDisconnect
recv - 接收數(shù)據(jù),如果接收到數(shù)據(jù),馬上調(diào)用handler->handlerReceiveData,接收發(fā)生錯(cuò)誤,表示連接斷開,調(diào)用handler->handlerDisconnect
5. ConnectionHandler一個(gè)抽象類,用來接收一個(gè)客戶端連接的請(qǐng)求,該類用于ConnectionTcpServer
只有一個(gè)接口:
handleIncomingConnection( ConnectionBase *connect ) - &connect表示新建立的連接請(qǐng)求,哪原始的socket做類比相當(dāng)于accept返回的socket.
注意: 區(qū)別于ConnectionDataHandler用于處理一個(gè)特定連接的中的事件(數(shù)據(jù)到來,連接斷開,連接建立),ConnectionListener用于XMPP Stream.
6. ConnectionTcpServer,實(shí)質(zhì)上就是一個(gè)偵聽socket,同原始的socket做類比就是一個(gè)調(diào)用了bind/listen之后處于偵聽狀態(tài)的socket.主要數(shù)據(jù)成員:
connectionHandler - 接收新到來的連接,接收到之后調(diào)用handlerIncomingConnection
主要方法:
connect - 建立套接字,綁定到本地地址,偵聽bind/listen
recv - 調(diào)用accept接收一個(gè)socket連接,如果成功,則用accpet返回的socket創(chuàng)建一個(gè)ConnectionTCPClient,調(diào)用handlerIncomingConnection來處理新進(jìn)的連接.
總結(jié):
ConnectionTcpServer和ConnectionTcpClient的區(qū)別:
connect (client) - 連接到服務(wù)器,使connection處于可以接收數(shù)據(jù)的狀態(tài)
connect(server) - 綁定到本地地址,偵聽,使connection處于可以接收新連接的狀態(tài)(accept)
recv(client) - 接收數(shù)據(jù),調(diào)用connectionDataHandler->handlerReceivedData
recv(server) - 接收新連接,調(diào)用connectionHandler->handlerIncomingConnection
receive(Client) - 接收數(shù)據(jù)狀態(tài),循環(huán)接收數(shù)據(jù),調(diào)用disconnect時(shí)退出
receive(Server) - 接收連接狀態(tài),循環(huán)接收連接,調(diào)用disconnect時(shí)退出.
所以ConnectionTcpClient有發(fā)送數(shù)據(jù)和循環(huán)接收數(shù)據(jù)的能力,ConnectionTcpServer有偵聽客戶端連接的能力。當(dāng)有特定的事件發(fā)生的時(shí)候,會(huì)自動(dòng)觸發(fā)相關(guān)的handler來進(jìn)行處理,如數(shù)據(jù)到來,連接建立\斷開,新連接到來等等。
問題:
這種設(shè)計(jì)模式使receive處于一個(gè)無限的while循環(huán),不斷的調(diào)用select+accpet或者select+receive,是否利于send之類的方法在同一個(gè)socket上發(fā)送數(shù)據(jù)?