diff --git a/TcpClient.cpp b/TcpClient.cpp new file mode 100644 index 0000000..f863b08 --- /dev/null +++ b/TcpClient.cpp @@ -0,0 +1,269 @@ +#include "StdAfx.h" +#include "TcpClient.h" +#include "QrGuide.h" +#include + + +CTcpClient::CTcpClient() +{ + WSADATA wsaData; + WORD wVersionRequested=MAKEWORD(2, 2); + if( 0 == WSAStartup (wVersionRequested, &wsaData)) + { + ; + } + + m_socket = NULL; + //m_hWnd = NULL; + m_sPort = 0; + memset(m_achSendBuf, 0, 1024); + + m_hReceive = NULL; + + m_bStart = FALSE; + + time(&m_lLastNetTime); + m_lLastConnectTime = 0; +} + +CTcpClient::~CTcpClient(void) +{ + m_bStart = FALSE; + closesocket(m_socket); + m_socket = NULL; + if (WAIT_TIMEOUT == WaitForSingleObject(m_hReceive, 3000)) + { + // + ASSERT(FALSE); + TerminateThread(m_hReceive, 0); + } +} + + +void CTcpClient::UnInit() +{ +} + +void CTcpClient::RegisterHwnd(HWND hWnd, PVOID pParent) +{ + m_hWnd = hWnd; + m_pParent = pParent; +} + + +//初始化网络配置, strConfName 为ini配置文件中的段名 +int CTcpClient::InitNetInfo(CString strConfName) +{ + CString strConf = theApp.m_strModulePath + "\\config.ini"; + + + char acIp[64] = {0}; + GetPrivateProfileString(strConfName, "IP", "0.0.0.0", acIp, 63, strConf); + + m_strServerIp = acIp; + + m_sPort = (short)GetPrivateProfileInt(strConfName, "PORT", 0, strConf); + + LogOutToFile("[info] 连接服务器:[%s][%s:%d]", strConfName.GetBuffer(), acIp, m_sPort); + + return 0; +} + +//初始化网络配置, strConfName 为ini配置文件中的段名 +int CTcpClient::InitNetInfo(CString strIp, int nPort) +{ + m_strServerIp = strIp; + m_sPort = nPort; + LogOutToFile("[info] 连接服务器:[%s:%d]", strIp.GetBuffer(), nPort); + return 0; +} + + +BOOL CTcpClient::ConnectServer() +{ + if (NULL != m_socket) + { + return FALSE; + } + + m_bStart = TRUE; + m_hReceive = (HANDLE)_beginthreadex(NULL, 0, recvThread, this, 0, NULL); + + return TRUE; +} + +int CTcpClient::StopConnect() +{ + if (NULL == m_socket || NULL == m_hReceive) + { + return 0; + } + + m_bStart = FALSE; + closesocket(m_socket); + if (WAIT_TIMEOUT == WaitForSingleObject(m_hReceive, 3000)) + { + // + ASSERT(FALSE); + TerminateThread(m_hReceive, 0); + m_socket = NULL; + return -1; + } + m_socket = NULL; + return 0; +} + +int CTcpClient::ReConnect() +{ + if (m_bStart == TRUE) + { + StopConnect(); + ConnectServer(); + } + return 0; +} + +void CTcpClient::PostMessage2MainWnd(UINT uMsg, WPARAM wParam, CString strMsg) +{ + NET_TCP_PACKET* pNetPacket = new NET_TCP_PACKET; + pNetPacket->pData = new char[strMsg.GetLength() + 1]; + memcpy(pNetPacket->pData, strMsg.GetBuffer(), strMsg.GetLength()); + strMsg.ReleaseBuffer(); + pNetPacket->pData[strMsg.GetLength()] = '\0'; + pNetPacket->lLen = strMsg.GetLength(); + ::PostMessage(this->m_hWnd, uMsg, wParam, (LPARAM)pNetPacket); +} + + +unsigned int __stdcall recvThread(LPVOID param) +{ + CTcpClient* pThis = (CTcpClient*)param; + + if (0 != pThis->m_socket) + { + LogOutToFile("网络服务已经启动,禁止多次连接."); + return 0; + } + + pThis->m_lLastConnectTime = 0; + time(&pThis->m_lLastConnectTime);//连续重连失败60分钟则平台重启 + while (pThis->m_bStart) + { + pThis->m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + sockaddr_in remote; + remote.sin_family = AF_INET; + remote.sin_addr.s_addr = inet_addr(pThis->m_strServerIp.GetBuffer()); + //remote.sin_addr.s_addr = inet_addr("127.0.0.1"); + remote.sin_port = htons(pThis->m_sPort); + + time(&pThis->m_lLastNetTime); + if (0 == connect(pThis->m_socket, (sockaddr*)&remote, sizeof(remote))) + { + LogOutToFile("网络已连接."); + pThis->PostMessage2MainWnd(WM_CAM_NETMESSAGE, NET_CAM_CONNECT_OK, "扫码头已连接"); + break; + } + else + { + CString strMsg; + strMsg.Format("连接扫码头%s失败,20秒后开始重连[%d].", pThis->m_strServerIp.GetBuffer(), GetLastError()); + LogOutToFile(strMsg); + pThis->PostMessage2MainWnd(WM_CAM_NETMESSAGE, NET_CAM_DISCONNECT, strMsg); + } + closesocket(pThis->m_socket); + pThis->m_socket = NULL; + for (int i = 0; i < 200 && TRUE == pThis->m_bStart; i++) + { + Sleep(100); + } + } + + pThis->m_lLastConnectTime = 0; + + //接受数据 + pThis->HandleNdcCMsg(); + + pThis->m_socket = NULL; + + pThis->PostMessage2MainWnd(WM_CAM_NETMESSAGE, NET_CAM_DISCONNECT, "扫码头已断开"); + + if (FALSE == pThis->m_bStart) + { + LogOutToFile("网络服务退出."); + return 0 ; + } + + LogOutToFile("网络连接异常断开,立即开始重连."); + + //断开后重新连接 + pThis->ConnectServer(); + return 0; +} + +int CTcpClient::SendData(char* pData, int lLen) +{ + + if (NULL == m_socket) + { + LogOutToFile("数据发送失败,网络还未连接"); + return -1; + } + + int lSend = send(m_socket, pData, lLen, 0); + return lSend; +} + +void CTcpClient::HandleNdcCMsg() +{ + char acBuffer[10240] = ""; + int nRecvLen = 0; + int nStateChange = 0; + + while (m_bStart) + { + int lRec = recv(m_socket, acBuffer + nRecvLen, 10240 - nRecvLen, 0); + + //TRACE("Recv len: %d\n", lRec); + if (lRec > 0) + { + nRecvLen += lRec; + } + else + { + LogOutToFile("Error: recv ret %d. error code %d", lRec, GetLastError()); + closesocket(m_socket); + return ; + } + + //消息体长度不足 + if (nRecvLen < 21)continue; + int nMsgLen = 21; + + + while (true) + { + NET_TCP_PACKET* pNetPacket = new NET_TCP_PACKET; + pNetPacket->pData = new char[nMsgLen + 1]; + memcpy(pNetPacket->pData, acBuffer, nMsgLen); + pNetPacket->pData[nMsgLen] = '\0'; + pNetPacket->lLen = nMsgLen; + ::PostMessage(this->m_hWnd, WM_CAM_NETMESSAGE, NET_CAM_DATA_MSG, (LPARAM)pNetPacket); + + //从缓存中去掉已处理的消息 + for (int i = nMsgLen; i < nRecvLen; i++) + { + acBuffer[i - nMsgLen] = acBuffer[i]; + } + nRecvLen -= nMsgLen; + + //不足一条消息长度 + if (nRecvLen < 21) + { + break; + } + } + } +} + +