agv-control/Plugin/QrGuide/TcpClient.cpp
2025-06-09 09:09:25 +08:00

271 lines
5.3 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "TcpClient.h"
#include "QrGuide.h"
#include <process.h>
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;
}
}
}
}