#include "CVrTCPClient.h" #include #include #include #include "VrError.h" #define MAX_DATA_LEN 1024 #define PROTOCL_START 0x09060002 #define PROTOCL_END 0x09060003 IVrTCPClient* IVrTCPClient::CreateInstance() { return new CVrTCPClient(); } void IVrTCPClient::DestroyInstance(IVrTCPClient* pInstance) { if (pInstance != nullptr) { delete pInstance; pInstance = nullptr; } } CVrTCPClient::CVrTCPClient() : m_nSocket(INVALID_SOCKET_VALUE) , m_bRecv(false) , m_bRecvWorking(false) , m_fRecvCallback(nullptr) , m_fLinkcCallback(nullptr) , m_bLink(false) { _Init(); } CVrTCPClient::~CVrTCPClient() { CloseDevice(); #ifdef _WIN32 WSACleanup(); #endif } int CVrTCPClient::LinkDevice(const std::string sDevIP, int nPort, bool bReLink, LinkEventFunc linkFunc) { m_fLinkcCallback = linkFunc; m_sIp = sDevIP; m_nPort = nPort; int nRet = _ExecLinkDev(sDevIP, nPort); if (SUCCESS == nRet) { m_bLink = true; if (m_fLinkcCallback) m_fLinkcCallback(true); } if (bReLink) { std::thread linkThread(&CVrTCPClient::_ReLinkDevThread, this); linkThread.detach(); return SUCCESS; } else { return nRet; } } int CVrTCPClient::StartWork(TCPRecvFunc callbackFunc) { if (m_bRecv) return SUCCESS; m_bRecv = true; m_fRecvCallback = callbackFunc; std::thread recvThread(&CVrTCPClient::_RecvData, this); recvThread.detach(); return SUCCESS; } int CVrTCPClient::CloseDevice() { if (m_bRecv) { m_bRecv = false; while (m_bRecvWorking) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } if (m_nSocket != INVALID_SOCKET_VALUE) { closesocket_func(m_nSocket); m_nSocket = INVALID_SOCKET_VALUE; } return SUCCESS; } bool CVrTCPClient::SendData(const char* pData, const int nLen) { bool bRet = true; int nSendLen = 0; do { int nCount = 0; if ((nCount = send(m_nSocket, pData + nSendLen, nLen - nSendLen, 0)) < 0) { printf("send faile"); bRet = false; break; } else { nSendLen += nCount; } } while (nSendLen < nLen); return bRet; } bool CVrTCPClient::_Init() { #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return false; } #endif return true; } void CVrTCPClient::_RecvData() { m_bRecvWorking = true; char recvData[MAX_BUF_LEN]; int recvLen = 0; while (m_bRecv) { timeval waitTime = {0, 1000}; fd_set rfd; FD_ZERO(&rfd); FD_SET(m_nSocket, &rfd); #ifdef _WIN32 int nCount = select(0, &rfd, NULL, NULL, &waitTime); #else int nCount = select(m_nSocket + 1, &rfd, NULL, NULL, &waitTime); #endif if (nCount <= 0) { continue; } memset(recvData, 0, MAX_BUF_LEN); //recv if ((recvLen = recv(m_nSocket, recvData, MAX_BUF_LEN, 0)) <= 0) { m_condRelink.notify_one(); continue; } if (m_fRecvCallback) { m_fRecvCallback(recvData, recvLen); } } m_bRecvWorking = false; } // �����豸 void CVrTCPClient::_ReLinkDevThread() { while (true) { if (m_bLink) { std::unique_lock lck(m_mutexRelink); m_condRelink.wait(lck); } m_bLink = ( 0 == _ExecLinkDev(m_sIp, m_nPort) ); if (m_fLinkcCallback) m_fLinkcCallback(m_bLink); } } int CVrTCPClient::_ExecLinkDev(std::string sIP, int nPort) { if (INVALID_SOCKET_VALUE != m_nSocket) { closesocket_func(m_nSocket); } m_nSocket = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET_VALUE == m_nSocket) { if (m_fLinkcCallback) m_fLinkcCallback(false); return ERR_CODE(NET_ERR_CREAT_INIT); } sockaddr_in sSockAddr; sSockAddr.sin_family = AF_INET; sSockAddr.sin_port = htons(nPort); #ifdef _WIN32 sSockAddr.sin_addr.S_un.S_addr = inet_addr(sIP.c_str()); #else inet_pton(AF_INET, sIP.c_str(), &sSockAddr.sin_addr); #endif int nRet = connect(m_nSocket, (sockaddr*)&sSockAddr, sizeof(sockaddr_in)); if (SOCKET_ERROR_VALUE == nRet) { printf("dev connect err [%d] errno : %d\n", nRet, errno); if (m_fLinkcCallback) m_fLinkcCallback(false); return ERR_CODE(NET_ERR_CONNECT); } int flag = 1; int ret = setsockopt(m_nSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag)); if (ret == -1) { printf("Couldn't setsockopt(TCP_NODELAY)\n"); } return SUCCESS; }