C++自定义封装socket操作业务类完整实例
时间:2021-06-08 07:45:15|栏目:C代码|点击: 次
本文实例讲述了C++自定义封装socket操作业务类。分享给大家供大家参考,具体如下:
Linux下C++封装socket操作的工具类(自己实现)
socketconnector.h
#ifndef SOCKETCONNECTOR_H #define SOCKETCONNECTOR_H #include "global.h" using namespace std; class SocketConnector { public: typedef enum { ENormal, EOther, } SocketState; public: static SocketConnector * getInstance(); inline SocketState state(){ return m_state; } inline void setState(SocketState _state){ m_state = _state; } inline bool isConnected() { return m_isConnected; } inline void setConnected(bool state) { m_isConnected = state; } void start(); inline void setServerIP(string ip){ m_server_ip = ip;} inline void setServerPort(int port){ m_server_port = port; } int connect_sockfd(); int onSendMessage(string & message); private: SocketConnector(); void onConnectToServer(string & ip,int port); static void * onReportMessage(void * p); static void * onReadMessage(void * p); static void * onWriteMessage(void * p); private: SocketState m_state; bool m_isConnected; int m_sockFd; string m_server_ip; int m_server_port; pthread_t m_report_tid; pthread_t m_read_tid; pthread_t m_write_tid; }; #endif // SOCKETCONNECTOR_H
socketconnector.cpp
#include "global.h" #include "socketconnector.h" #include "cmessagecenter.h" #include "cmip_requestparser.h" #include "csettings.h" #include "datadef.h" #include "cstringutils.h" using namespace std; static SocketConnector * g_instance = NULL; /************************************************************************************************** * Single Instance. ***************************************************************************************************/ SocketConnector * SocketConnector::getInstance() { if (g_instance == NULL) { g_instance = new SocketConnector(); } return g_instance; } /************************************************************************************************** * Consturoctor ***************************************************************************************************/ SocketConnector::SocketConnector() { m_isConnected = false; m_state = ENormal; } /************************************************************************************************** * Connect to Server By Blocking Method. ***************************************************************************************************/ void SocketConnector::onConnectToServer(string & ip,int port){ cout << __FUNCTION__ << "connecting::[" << ip << " , " << port << "]" << endl; struct timeval send_timeout; send_timeout.tv_sec = 5; send_timeout.tv_usec = 0; int keepalive = 1; int keepidle = 10; int keepinterval = 5; int keepcount = 3; int value = 0; socklen_t len = sizeof(int); static struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr(ip.c_str()); do { m_sockFd = socket(AF_INET, SOCK_STREAM, 0); if ( -1 == m_sockFd ) { sleep(1); continue; } }while(-1 == m_sockFd); if(setsockopt(m_sockFd, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)) == -1) { printf("setsockopt SO_SNDTIMEO fail\n"); } if(setsockopt(m_sockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive )) == -1) { printf("setsockopt SO_KEEPALIVE fail\n"); } if(setsockopt(m_sockFd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle )) == -1) { printf("setsockopt TCP_KEEPIDLE fail\n"); } if(setsockopt(m_sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval )) == -1) { printf("setsockopt TCP_KEEPINTVL fail\n"); } if(setsockopt(m_sockFd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount )) == -1) { printf("setsockopt TCP_KEEPCNT fail\n"); } getsockopt(m_sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&value, &len); cout << __FUNCTION__ << "sockFd KeepIntval::[" << value << endl; while (!m_isConnected) { if(connect(m_sockFd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == 0) { m_isConnected = true; break; } else { if ( ECONNREFUSED == errno) { m_isConnected = false; sleep(1); printf("Reconnect To Server:%s Port:%d\n", m_server_ip.c_str(), m_server_port); } else { m_isConnected = false; perror("connected() error()"); exit(-1); } } } } /************************************************************************************************** * Create Report Thread; * Create Read Thread; * Create Write Thread; * MainThread wait the subThreads exits; ***************************************************************************************************/ void SocketConnector::start() { m_sockFd = connect_sockfd(); cout << __FUNCTION__ << "Will Create Report|Read|Write Thread." << endl; pthread_create(&m_report_tid,NULL, onReportMessage, this); /* report to cmdmodule*/ pthread_create(&m_read_tid, NULL, onReadMessage, this); /* read from cmdmodule*/ pthread_create(&m_write_tid, NULL, onWriteMessage, this); /* reply to cmdmodule*/ pthread_join(m_read_tid,NULL); pthread_join(m_write_tid,NULL); pthread_join(m_report_tid,NULL); } /************************************************************************************************** * Used to Get connected socket fd. * if connected, return directly. * if not connected,try to create connect fd. ***************************************************************************************************/ int SocketConnector::connect_sockfd() { if ( m_isConnected == true) { cout << __FUNCTION__ << "::Socket is Already Connected." << endl; return m_sockFd; } cout << __FUNCTION__ << "::Will Try to Connect to Server." << endl; onConnectToServer(m_server_ip, m_server_port); return m_sockFd; } /************************************************************************************************** * Report Status to CmdModule Thread. * every 2s ,report one message to cmdwifi. ***************************************************************************************************/ void * SocketConnector::onReportMessage(void * p) { SocketConnector * connector = (SocketConnector *)(p); if ( NULL == p) { cout << __FUNCTION__ << "onSelectSocket() Error: param [connector] is NULL" << endl; return NULL; } string content; int devType = atoi(CSettings::getInstance()->getKuType().c_str()); int report_interval = atoi(CSettings::getInstance()->getKuReportinterval().c_str()); string position = CSettings::getInstance()->getKuPosition(); string local_ip = CSettings::getInstance()->getKuAgentip(); cout << endl; cout << "###################################" << endl; cout << "Local-IP::" << local_ip << endl; cout << "Ku-CMA-Pos::" << position << endl; cout << "Ku-CMA-Type::" << devType << endl; cout << "###################################" << endl; cout << endl; while(true) { int state = connector->state(); content = "<status>" + CStringUtils::toString(state) + "</status>"; content += "<type>" + CStringUtils::toString(devType) + "</type>"; content += "<site>" + position + "</site>"; content += "<ip>" + local_ip + "</ip>"; Response resp(STATUS_REPORT_CMD,0,string(content)); CMessageCenter::getInstance()->addReply(resp); sleep(report_interval); } } /************************************************************************************************** * Read Message from Connection. * Then Send Message to MessageCenter Queue. ***************************************************************************************************/ void * SocketConnector::onReadMessage(void * p) { SocketConnector * connector = (SocketConnector *)(p); if ( NULL == p) { cout << __FUNCTION__ << "onSelectSocket() Error: param [connector] is NULL" << endl; return NULL; } int sockFd = connector->connect_sockfd(); fd_set fds; struct timeval timeout={0,0}; const int BUFFER_LEN = 4*1024; static char buffer[BUFFER_LEN]={0}; while(true) { FD_ZERO(&fds); FD_SET(sockFd,&fds); int ret = select(sockFd + 1,&fds,NULL,NULL,&timeout); switch (ret) { case -1:/*Error process*/ { perror("select()"); if ( EBADF == errno) { close(sockFd); connector->setConnected(false); sleep(1); sockFd = connector->connect_sockfd(); continue; } if ( EINTR == errno || ENOMEM == errno) { sleep(1); continue; } }break; case 0: { //cout << "select() timeout! " << endl; }break; default: { if(FD_ISSET(sockFd,&fds)) { memset(buffer, 0, BUFFER_LEN); int nRead = read(sockFd, buffer, BUFFER_LEN); cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl; cout << "From Server Recevied Data::" << string(buffer) << endl; cout << "From Server Recevied Length::" << nRead << endl; cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl; CRequestParser parser; Request req; int ret = parser.parseToMessage(buffer,&req); if (0 != ret) { cout << __FUNCTION__ << "Request Format is invalid" << endl; continue; } req.print(); CMessageCenter::getInstance()->addRequest(req); } }break; } } } /************************************************************************************************** * Write Message to Connection. * Then Send Message to MessageCenter Queue. ***************************************************************************************************/ void * SocketConnector::onWriteMessage(void * p) { SocketConnector * connector = (SocketConnector *)(p); if ( NULL == p) { cout << __FUNCTION__ << "onSelectSocket() Error: param [connector] is NULL" << endl; return NULL; } while (true) { Response msg; CMessageCenter::getInstance()->getReplyMsg(msg); string data = CMessageEncoder(msg).encode(); connector->onSendMessage(data); } } /************************************************************************************************** * Send Message By Socket. ***************************************************************************************************/ int SocketConnector::onSendMessage(string & strSend) { if (atoi(CSettings::getInstance()->getDebugMode().c_str()) == 1) { cout << __FUNCTION__ << "Send To Cmdwifi Data::" << endl; cout << strSend << endl; } int sock = m_sockFd; char *pData = &strSend[0]; int nLen = static_cast<int>(strSend.size()); int nTotal = nLen; int i = 0; while(1) { int nTmp = send(sock, &pData[i], nTotal, 0); if (nTmp <= 0) { close(sock); return -1; } nTotal -= nTmp; i += nTmp; if (nTotal <= 0) { break; } } return 0; }
希望本文所述对大家C++程序设计有所帮助。