一个基于ASIO异步读写的客户端类实现,使用了类委托方法。使它可以不使用派生就可以获得数据发送接收的控制。这个使用了boost和我的tinyC++库(http://www.cppblog.com/zdhsoft/archive/2010/09/08/126172.html)。这个例子,希望可以给大家做为学习ASIO的异常客户端例子。
具体实现如下:
1 #ifndef _X_ASIO_CLIENT_H_
2 #define _X_ASIO_CLIENT_H_
3 #include "xasio_head.h"
4 #include "xdelegate.h"
5 #include "xbuffer.h"
6 #include "xdatetime.h"
7 template<int NSIZE = 128>
8 class XASIOClient
9 {
10 public:
11 XASIOClient(boost::asio::io_service & paramIOService)
12 :m_Socket(paramIOService),
13 m_WaitTime(paramIOService),
14 m_Connected(false),
15 m_WaitTimeCancelFlag(false),
16 m_LastReadTime(0)
17 {
18 }
19
20 ~XASIOClient()
21 {
22
23 }
24
25 bool Connect(const char * paramServerIP, unsigned short int paramServerPort, int paramTimeout = 5000)
26 {
27 if( isConnected() ) return false;
28
29 m_Socket.get_io_service().reset();
30 m_ErrorCode.assign(0,boost::system::get_system_category());
31 m_WaitTimeCancelFlag = false;
32 boost::asio::ip::tcp::endpoint epServer(boost::asio::ip::address_v4::from_string(paramServerIP), paramServerPort);
33 m_WaitTime.expires_from_now( boost::posix_time::milliseconds(paramTimeout));
34 m_Socket.async_connect(epServer, boost::bind(&XASIOClient::DoConnectEvent,this,_1,epServer));
35 m_WaitTime.async_wait(boost::bind(&XASIOClient::DoConnectedTimeOutEvent,this));
36 m_Socket.get_io_service().run();
37 return isConnected();
38
39 }
40 bool isConnected() const
41 {
42 return m_Connected;
43 }
44 const boost::system::error_code & getErrorCode() const
45 {
46 return m_ErrorCode;
47 }
48 boost::asio::ip::tcp::socket & getSocket()
49 {
50 return m_Socket;
51 }
52 void StartRead(int paramTimeout = 3000)
53 {
54 if( !isConnected() ) return;
55 m_Socket.get_io_service().reset();
56 EventOnReadBefore.Invoke(m_Socket);
57 m_LastReadTime = zdh::GetNowDateTime(); //设置超时时间
58 m_Socket.async_read_some(boost::asio::buffer(m_ReadBuffer),boost::bind(&XASIOClient::DoReadEvent,this,_1,_2, paramTimeout));
59 m_Socket.get_io_service().run();
60 EventOnReadAfter.Invoke(m_Socket);
61 }
62 void StartWrite(void * paramSendData, int paramSendDataBytes, int paramTimeout = 3000)
63 {
64 if( !isConnected() ) return;
65 EventOnWriteBefore.Invoke(m_Socket);
66 m_Socket.get_io_service().reset();
67 m_WaitTimeCancelFlag = false;
68 m_WaitTime.expires_from_now(boost::posix_time::milliseconds(paramTimeout));
69 m_Socket.async_write_some(boost::asio::buffer(paramSendData,paramSendDataBytes), boost::bind(&XASIOClient::DoWriteEvent,this,_1,_2,paramSendData,paramSendDataBytes,paramTimeout));
70 m_WaitTime.async_wait(boost::bind(&XASIOClient::DoWriteTimeOutEvent,this));
71 m_Socket.get_io_service().run();
72 EventOnWriteAfter.Invoke(m_Socket);
73 }
74 private:
75 void DoWriteTimeOutEvent()
76 {
77 if( !m_WaitTimeCancelFlag ) //如没有被取消,则执行Timeout事件
78 {
79 EventOnWriteTimeout.Invoke(m_Socket);
80 }
81 }
82 void DoWriteEvent(const boost::system::error_code & paramErrorCode, std::size_t paramBytesTransferred,void * paramSendData, int paramSendDataBytes, int paramTimeout )
83 {
84 m_WaitTime.expires_from_now(boost::posix_time::milliseconds(paramTimeout));
85 m_WaitTime.async_wait(DoWriteTimeOutEvent);
86
87 if( !paramTimeout)
88 {
89 m_ErrorCode = paramErrorCode;
90 EventOnWriteError.Invoke( m_Socket, paramErrorCode );
91 return;
92 }
93 if( paramBytesTransferred > 0)
94 {
95 EventOnWrite.Invoke(m_Socket, (int)paramBytesTransferred, paramSendData, paramSendDataBytes );
96 }
97 }
98 void DoReadEvent(const boost::system::error_code & paramErrorCode,std::size_t paramBytes_Transfered,int paramTimeout)
99 {
100
101 bool bContinue = true;
102 if( paramBytes_Transfered > 0 ) //如果有接收到数据
103 {
104 m_LastReadTime = zdh::GetNowDateTime();//有数据到达,重置Timeout时间
105 EventOnRead.Invoke(m_Socket, m_ReadBuffer, intparamBytes_Transfered, bContinue);
106 }
107 if( bContinue && (zdh::GetNowDateTime() - m_LastReadTime) > paramTimeout )
108 {
109 //如果超时
110 bContinue = false;
111 EventOnReadTimeout.Invoke(m_Socket);
112
113 }
114 if( bContinue && isConnected())
115 {
116 m_Socket.async_read_some(boost::asio::buffer(m_ReadBuffer),boost::bind(&XASIOClient::DoReadEvent,this,_1,_2, paramTimeout));
117 }
118 }
119 void DoConnectedTimeOutEvent()
120 {
121 if( !m_WaitTimeCancelFlag ) //如没有被取消,则执行Timeout事件
122 {
123 EventOnConnectTimeout.Invoke(m_Socket);
124 }
125 }
126
127 void DoConnectEvent(const boost::system::error_code & paramErrorCode, const boost::asio::ip::tcp::endpoint & paramEndPoint)
128 {
129 m_WaitTimeCancelFlag = true; //取消timeout事件
130 m_WaitTime.cancel();
131
132 m_Connected = !paramErrorCode;
133 m_ErrorCode = paramErrorCode;
134 EventOnConnent.Invoke(m_Socket, paramErrorCode, paramEndPoint);
135 }
136 public:
137 //连接事件
138 //void OnConnectTimeout(boost::asio::ip::tcp::socket & paramSocket);
139 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnConnectTimeout;
140 //void OnConnect(boost::asio::ip::tcp::socket & paramSocket,const boost::system::error_code & paramErrorCode, const boost::asio::ip::tcp::endpoint & paramServerPoint);
141 zdh::XDelegate3<boost::asio::ip::tcp::socket &,const boost::system::error_code &, const boost::asio::ip::tcp::endpoint &> EventOnConnent;
142
143 //读取事件
144 //void OnReadBefore(boost::asio::ip::tcp::socket & paramSocket);
145 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnReadBefore;
146 //void OnReadAfter(boost::asio::ip::tcp::socket & paramSocket);
147 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnReadAfter;
148 //void OnRead(boost::asio::ip::tcp::socket & paramSocket, void * paramReadData, int paramReadBytes, bool paramContinue);
149 zdh::XDelegate4<boost::asio::ip::tcp::socket &,void *, int,bool &> EventOnRead;
150 //void OnReadTimeout(boost::asio::ip::tcp::socket & paramSocket);
151 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnReadTimeout;
152
153 //写入事件
154 //void OnWriteBefore(boost::asio::ip::tcp::socket & paramSocket);
155 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnWriteBefore;
156 //void OnWriteAfter(boost::asio::ip::tcp::socket & paramSocket);
157 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnWriteAfter;
158 //void OnWrite(boost::asio::ip::tcp::socket & paramSocket, int paramWriteBytes,void * paramWriteData, int paramWriteDataBytes);
159 zdh::XDelegate4<boost::asio::ip::tcp::socket &,int, void *, int> EventOnWrite;
160 //void OnWriteTimeout(boost::asio::ip::tcp::socket & paramSocket);
161 zdh::XDelegate1<boost::asio::ip::tcp::socket &> EventOnWriteTimeout;
162 //void OnWriteError(boost::asio::ip::tcp::socket & paramSocket, boost::asio::error_code & paramCode);
163 zdh::XDelegate2<boost::asio::ip::tcp::socket &, boost::system::error_code &> EventOnWriteError;
164
165 private:
166 boost::asio::ip::tcp::socket m_Socket; ///<连接句柄
167
168 boost::asio::deadline_timer m_WaitTime; ///<用于检查超时服务器定时器
169 bool m_WaitTimeCancelFlag; ///<True表示m_WaitTime产生的事件无效,false表示有效
170
171 bool m_Connected;
172 boost::system::error_code m_ErrorCode; ///<最后出标志
173 zdh::XLong m_LastReadTime; ///<最近一次读取数据的时间
174
175 zdh::XByte m_ReadBuffer[NSIZE];
176
177 };
178 #endif
179