GrabBag/VrNets/TCPClient/Src/CVrTCPClient.cpp

235 lines
4.4 KiB
C++
Raw Blame History

#include "CVrTCPClient.h"
#include <sstream>
#include <thread>
#include <chrono>
#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;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>
void CVrTCPClient::_ReLinkDevThread()
{
while (true)
{
if (m_bLink)
{
std::unique_lock<std::mutex> 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;
}