tcpclient.h
#pragma once #include <boost/function.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <iostream> #include <vector> #include <string> using namespace boost::asio; #define TCP_RECV_DATA_PACKAGE_MAX_LENGTH 1024 //Receive data type typedef enum RecvDataType { RecvDataType_NoKnown = 0x00, //unknown RecvDataType_Head = 0x01, //head data RecvDataType_Body = 0x02, //body data RecvDataType_Some = 0x03, //Partial data RecvDataType_OnePackage = 0x04, // whole package data }; // send data callback function typedef void (CALLBACK *TcpSendDataCallback)(const boost::system::error_code& error,std::size_t bytes_transferred,DWORD dwUserData1,DWORD dwUserData2); //Receive data callback function typedef void (CALLBACK *TcpRecvDataCallback)(const boost::system::error_code& error,char *pData,int nDataSize,DWORD dwUserData1,DWORD dwUserData2); class TcpClient { public: TcpClient(void); virtual ~TcpClient(void); //Setting parameters void SetParameter(unsigned int uiSendBufferSize,unsigned int uiSendTimeout,unsigned int uiRecvBufferSize,unsigned int uiRecvTimeout); //Set blocking and non-blocking void SetNoBlock(bool bNoBlock); //connect to the server (sync) int ConnectServer(char *pIp,unsigned short usPort,unsigned int uiConnectTimeout); //connect to the server (async) int ConnectServerByAynsc(char *pIp,unsigned short usPort,unsigned int uiConnectTimeout,unsigned int uiReconnectInteralTime); //close the connection void CloseConnect(); //send data int SendData(char *pBuffer,int nBufferSize); //Receive data int RecvData(char *pBuffer,int nBufferSize); //Receive data (blocking) int RecvDataByBlock(char *pBuffer,int nBufferSize); //Send data (async) int SendDataByAynsc(char *pBuffer,int nBufferSize,TcpSendDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2); //Receive data (async) int RecvDataByAynsc(TcpRecvDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2); protected: void connect_handler(const boost::system::error_code& ec); void async_read_handler(const boost::system::error_code& ec,size_t bytes_transferred,TcpRecvDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2); void read_hander(char *pBuffer,size_t bytes_transferred,const boost::system::error_code& err); void write_handler(const boost::system::error_code& error,size_t bytes_transferred,TcpSendDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2); void RecvDataTimeoutProcess(); io_service m_io; ip::tcp::endpoint * m_pEndPoint; ip::tcp::socket * m_pSocket; boost::array<char,TCP_RECV_DATA_PACKAGE_MAX_LENGTH> m_rbTempRecvBuffer; //Temporarily receive data buffer int m_nSyncRecviceDataSize; //Sync receive data size unsigned int m_uiSendBufferSize; unsigned int m_uiSendTimeout; unsigned int m_uiRecvBufferSize; unsigned int m_uiRecvTimeout; deadline_timer * m_pTimer; };
tcpclient.cpp
#include "StdAfx.h" #include "TcpClient.h" TcpClient::TcpClient(void) { m_uiSendBufferSize = 0; m_uiSendTimeout = 10000; m_uiRecvBufferSize = 0; m_uiRecvTimeout = 10000; m_pEndPoint = NULL; m_pSocket = NULL; m_nSyncRecviceDataSize = 0; m_pTimer = new deadline_timer(m_io); } TcpClient::~TcpClient(void) { } //Setting parameters void TcpClient::SetParameter(unsigned int uiSendBufferSize,unsigned int uiSendTimeout,unsigned int uiRecvBufferSize,unsigned int uiRecvTimeout) { m_uiSendBufferSize = uiSendBufferSize; m_uiSendTimeout = uiSendTimeout; m_uiRecvBufferSize = uiRecvBufferSize; m_uiRecvTimeout = uiRecvTimeout; if(m_uiRecvTimeout <= 0) { m_uiRecvTimeout = 10000; } } //connect to the server (sync) int TcpClient::ConnectServer(char *pIp,unsigned short usPort,unsigned int uiConnectTimeout) { if(pIp == NULL || usPort == 0) return -1; try { m_pEndPoint = new ip::tcp::endpoint(ip::address::from_string(pIp), usPort); m_pSocket = new ip::tcp::socket(m_io); m_pSocket->open(m_pEndPoint->protocol()); m_pSocket->set_option(boost::asio::ip::tcp::socket::reuse_address(true)); if(m_uiSendBufferSize != 0) { boost::asio::socket_base::send_buffer_size sendBufferSize(m_uiSendBufferSize); m_pSocket->set_option(sendBufferSize); } if(m_uiRecvBufferSize != 0) { boost::asio::socket_base::receive_buffer_size recvBufferSize(m_uiRecvBufferSize); m_pSocket->set_option(recvBufferSize); } //connect m_pSocket->connect(*m_pEndPoint); /* char str[1024]; sock.read_some(buffer(str)); std::cout << "receive from" << sock.remote_endpoint().address() << std::endl;; std::cout << str << std::endl; */ } catch (std::exception& e) { std::cout << e.what() << std::endl; return -2; } return 0; } //connect to the server (async) int TcpClient::ConnectServerByAynsc(char *pIp,unsigned short usPort,unsigned int uiConnectTimeout,unsigned int uiReconnectInteralTime) { if(pIp == NULL || usPort == 0) return -1; try { m_pEndPoint = new ip::tcp::endpoint(ip::address::from_string(pIp), usPort); m_pSocket = new ip::tcp::socket(m_io); m_pSocket->open(m_pEndPoint->protocol()); m_pSocket->set_option(boost::asio::ip::tcp::socket::reuse_address(true)); if(m_uiSendBufferSize != 0) { boost::asio::socket_base::send_buffer_size sendBufferSize(m_uiSendBufferSize); m_pSocket->set_option(sendBufferSize); } if(m_uiRecvBufferSize != 0) { boost::asio::socket_base::receive_buffer_size recvBufferSize(m_uiRecvBufferSize); m_pSocket->set_option(recvBufferSize); } //connect m_pSocket->async_connect(*m_pEndPoint,boost::bind(&TcpClient::connect_handler,this, boost::asio::placeholders::error)); } catch (std::exception& e) { std::cout << e.what() << std::endl; return -2; } return 0; } void TcpClient::connect_handler(const boost::system::error_code& ec) { if (ec) { return; } std::cout << "receive from:" << m_pSocket->remote_endpoint().address() << std::endl; } void TcpClient::async_read_handler(const boost::system::error_code& ec,size_t bytes_transferred,TcpRecvDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2) { // callback data if(fnCallback != NULL) { fnCallback(ec,m_rbTempRecvBuffer.data(),bytes_transferred,dwUserData1,dwUserData2); } if(ec == boost::asio::error::eof) { //The peer closes the connection if(m_pSocket->is_open()) { m_pSocket->close(); } //printf("close connect \n"); return; } if(ec != NULL) { // failed to send data return; } //Receive next data m_pSocket->async_read_some(boost::asio::buffer(m_rbTempRecvBuffer), boost::bind(&TcpClient::async_read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, fnCallback,dwUserData1,dwUserData2)); } //close the connection void TcpClient::CloseConnect() { if(m_pSocket != NULL) { m_pSocket->close(); m_pSocket = NULL; } } //send data int TcpClient::SendData(char *pBuffer,int nBufferSize) { int nRet = 0; if(m_pSocket != NULL) { nRet = m_pSocket->send(buffer(pBuffer,nBufferSize)); } return nRet; } //Receive data int TcpClient::RecvData(char *pBuffer,int nBufferSize) { int nRet = 0; if(m_pSocket != NULL) { m_nSyncRecviceDataSize = 0; boost::system::error_code ec; m_pSocket->async_read_some(buffer(pBuffer,nBufferSize),boost::bind(&TcpClient::read_hander,this,pBuffer,boost::asio::placeholders::bytes_transferred,boost::asio::placeholders::error)); m_pTimer->expires_from_now(boost::posix_time::seconds(m_uiRecvTimeout)); m_pTimer->async_wait(boost::bind(&TcpClient::RecvDataTimeoutProcess,this)); m_io.reset(); m_io.run(ec); nRet = m_nSyncRecviceDataSize; } return nRet; } void TcpClient::read_hander(char *pBuffer,size_t bytes_transferred,const boost::system::error_code& err) { if (err) { return; } m_nSyncRecviceDataSize = bytes_transferred; m_pTimer->cancel(); } void TcpClient::RecvDataTimeoutProcess() { int n = 0; } //Receive data (blocking) int TcpClient::RecvDataByBlock(char *pBuffer,int nBufferSize) { int nRet = 0; if(m_pSocket != NULL) { m_nSyncRecviceDataSize = 0; boost::system::error_code ec; m_pSocket->receive(buffer(pBuffer,nBufferSize)); } return nRet; } //Send data (async) int TcpClient::SendDataByAynsc(char *pBuffer,int nBufferSize,TcpSendDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2) { if(pBuffer == NULL || nBufferSize == 0) return -1; if(m_pSocket == NULL || !m_pSocket->is_open()) return -1; boost::asio::async_write( *m_pSocket, boost::asio::buffer(pBuffer,nBufferSize), boost::bind(&TcpClient::write_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, fnCallback,dwUserData1,dwUserData2)); return 0; } //Receive data (async) int TcpClient::RecvDataByAynsc(TcpRecvDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2) { if(m_pSocket == NULL || !m_pSocket->is_open()) return -1; m_pSocket->async_read_some(buffer(m_rbTempRecvBuffer),boost::bind(&TcpClient::async_read_handler, this, boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred,fnCallback,dwUserData1,dwUserData2)); return 0; } //Set blocking and non-blocking void TcpClient::SetNoBlock(bool bNoBlock) { if(m_pSocket == NULL) return; if(bNoBlock) { boost::asio::ip::tcp::socket::non_blocking_io io_option(true); m_pSocket->io_control(io_option); } else { //block boost::asio::ip::tcp::socket::non_blocking_io io_option(false); m_pSocket->io_control(io_option); } } void TcpClient::write_handler(const boost::system::error_code& error,size_t bytes_transferred,TcpSendDataCallback fnCallback,DWORD dwUserData1,DWORD dwUserData2) { if(fnCallback != NULL) { fnCallback(error,bytes_transferred,dwUserData1,dwUserData2); } if(error == boost::asio::error::eof) { //The peer closes the connection if(m_pSocket->is_open()) { m_pSocket->close(); } //printf("close connect \n"); return; } if(error != NULL) { // failed to send data return; } #ifdef _DEBUG //write data printf("write data!!!\n"); #endif }