#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; } } } }