gloox代码分析1 - connect模块

来源:互联网 发布:java实现单链表反转 编辑:程序博客网 时间:2024/05/17 03:48

主要分析gloox的connect模块,涉及的文件:
connectionbase.h
connectiondatahander.h
connectionhandler.h
connectiontcpbase.h (connectiontcpbase.cpp)
connectiontcpclient.h (connectiontcpclient.cpp)
connectiontcpserver.h (connectiontcpserver.cpp)

1. ConnectionBase抽象连接类,表示一个socket连接。
3个数据成员:
server和ip - 需要连接到的目标地址和端口(在ConnectionTcpServer是要绑定的本地地址)
connectionState - 连接的当前状态 (一个三种状态disconnected | connecting | connected)
connectionDataHandler - 处理三类ConnectionBase中的三类事件 ( 数据接收 | 连接建立 | 连接断开 )
5个主要方法:
connect - 建立一个socket连接
disconnect - 断开一个socket连接
send - 发送数据,该方法直到要发送的数据全部发送完毕才返回
recv( int timeout ) - 接收数据,接收到数据或者timeout返回
receive - 把connection设置成"接收模式",也就是循环的调用recv接收数据,直到连接断开该方法返回,
               该方法保证这个连接可以循环的接收数据.

注意: recv和receive的区别。


2. ConnectionDataHandler处理继承自ConnectionBase的对象的事件
handlerReceivedData - 接收到数据
handlerConnect - 一个原始的套接字连接建立
handlerDisconnect - 一个原始的套接字连接断开

3. ConnectionTcpBase一个基本的TCP连接,继承自ConnectionBase
数据成员
bool cancel - 表示连接是否应该断开,默认为true. (true表示连接断开)
                     函数disconnect也就是仅仅设置cancel为true.
                     在函数receive循环接收数据的逻辑中会检测cancel,如果为true,则表示连接断开,则返回,退出"接收模式"
int bufSize - buf的大小,默认是1024
char* buf - 缓冲区,大小事bufSize + 1 (在ConnectionTcpBase中并没有用到这个缓冲区,供上层使用E.g. ConnectionTcpClient的recv来接收数据)

实现的主要方法:
send - 发送数据
receive - "循环"接收数据
dataAvailable( int timeout ) - 一个私有方法,作用是测试socket上目前是否有数据可读,如果有返回true. 可以供recv调用. 避免了阻塞的调用原始套接字方法::receive或者::accept.

4. ConnectionTcpClient实现一个基本的TCP连接,继承自ConnectionTcpBase
实现的主要方法
connect - 连接到目标地址,如果成功,则调用handler->handlerConnect,失败则调用handler->handlerDisconnect
recv - 接收数据,如果接收到数据,马上调用handler->handlerReceiveData,接收发生错误,表示连接断开,调用handler->handlerDisconnect

5. ConnectionHandler一个抽象类,用来接收一个客户端连接的请求,该类用于ConnectionTcpServer
只有一个接口:
handleIncomingConnection( ConnectionBase *connect ) - &connect表示新建立的连接请求,哪原始的socket做类比相当于accept返回的socket.

注意: 区别于ConnectionDataHandler用于处理一个特定连接的中的事件(数据到来,连接断开,连接建立),ConnectionListener用于XMPP Stream.

6. ConnectionTcpServer,实质上就是一个侦听socket,同原始的socket做类比就是一个调用了bind/listen之后处于侦听状态的socket.
主要数据成员:
connectionHandler - 接收新到来的连接,接收到之后调用handlerIncomingConnection
主要方法:
connect - 建立套接字,绑定到本地地址,侦听bind/listen
recv - 调用accept接收一个socket连接,如果成功,则用accpet返回的socket创建一个ConnectionTCPClient,调用handlerIncomingConnection来处理新进的连接.

总结:
ConnectionTcpServer和ConnectionTcpClient的区别:
connect (client) - 连接到服务器,使connection处于可以接收数据的状态
connect(server) - 绑定到本地地址,侦听,使connection处于可以接收新连接的状态(accept)

recv(client) - 接收数据,调用connectionDataHandler->handlerReceivedData
recv(server) - 接收新连接,调用connectionHandler->handlerIncomingConnection

receive(Client) - 接收数据状态,循环接收数据,调用disconnect时退出
receive(Server) - 接收连接状态,循环接收连接,调用disconnect时退出.

所以ConnectionTcpClient有发送数据和循环接收数据的能力,ConnectionTcpServer有侦听客户端连接的能力。当有特定的事件发生的时候,会自动触发相关的handler来进行处理,如数据到来,连接建立/断开,新连接到来等等。

问题:
这种设计模式使receive处于一个无限的while循环,不断的调用select+accpet或者select+receive,是否利于send之类的方法在同一个socket上发送数据?

原创粉丝点击