Files
2026-03-03 13:56:44 +08:00

539 lines
13 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 "ClientSocket.h"
//////////////////////////////////////////////////////////////////////////
//宏定义
#define ID_SOCKET_WND 10 //SOCKET 窗口 ID
#define WM_SOCKET_NOTIFY WM_USER+10 //SOCKET 消息
//////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CClientSocket, CWnd)
ON_MESSAGE(WM_SOCKET_NOTIFY,OnSocketNotify)
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////////
//构造函数
CClientSocket::CClientSocket()
{
m_wRecvSize=0;
m_cbSendRound=0;
m_cbRecvRound=0;
m_dwSendXorKey=0;
m_dwRecvXorKey=0;
m_dwSendTickCount=0;
m_dwRecvTickCount=0;
m_dwSendPacketCount=0;
m_dwRecvPacketCount=0;
//m_cbSocketStatus=SHUT_REASON_NORMAL;
m_hSocket=INVALID_SOCKET;
m_pIClientSocketSink = NULL;
//m_ProxyInfo.wProxyPort=0;
//m_ProxyInfo.cbProxyType=PROXY_NONE;
m_cbSocketStatus=SOCKET_STATUS_IDLE;
}
//析构函数
CClientSocket::~CClientSocket()
{
CloseSocket();
}
//接口查询
void * CClientSocket::QueryInterface(const IID & Guid, DWORD dwQueryVer)
{
QUERYINTERFACE(IClientSocket, Guid, dwQueryVer);
QUERYINTERFACE_IUNKNOWNEX(IClientSocket, Guid, dwQueryVer);
return NULL;
}
//设置接口
bool CClientSocket::SetTCPSocketSink(IUnknownEx * pIUnknownEx)
{
ASSERT(pIUnknownEx!=NULL);
m_pIClientSocketSink = (IClientSocketSink *)pIUnknownEx->QueryInterface(IID_IClientSocketSink, VER_IClientSocketSink);
ASSERT(m_pIClientSocketSink != NULL);
return (m_pIClientSocketSink != NULL);
}
//获取接口
void * CClientSocket::GetTCPSocketSink(const IID & Guid, DWORD dwQueryVer)
{
if (m_pIClientSocketSink == NULL) return NULL;
return m_pIClientSocketSink->QueryInterface(Guid, dwQueryVer);
}
//连接服务器
BYTE CClientSocket::Connect(DWORD dwServerIP, WORD wPort)
{
//效验参数
ASSERT(m_hSocket==INVALID_SOCKET);
ASSERT(m_cbSocketStatus==SOCKET_STATUS_IDLE);
//效验状态
if (m_hSocket!=INVALID_SOCKET) throw TEXT("连接 SOCKET 句柄已经存在");
if (m_cbSocketStatus!=SOCKET_STATUS_IDLE) throw TEXT("连接状态不是等待连接状态");
if (dwServerIP==INADDR_NONE) throw TEXT("目标服务器地址格式不正确,请检查后再次尝试!");
//设置参数
m_wRecvSize=0;
m_cbSendRound=0;
m_cbRecvRound=0;
m_dwSendXorKey=0x12345678;
m_dwRecvXorKey=0x12345678;
m_dwSendTickCount=GetTickCount()/1000L;
m_dwRecvTickCount=GetTickCount()/1000L;
try
{
//建立 SOCKET
m_hSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (m_hSocket==INVALID_SOCKET) throw TEXT("SOCKET 创建失败");
if ((m_hWnd==NULL)&&(!Create(NULL,NULL,WS_CHILD,CRect(0,0,0,0),GetDesktopWindow(),ID_SOCKET_WND,NULL)))
throw TEXT("SOCKET 内部窗口创建失败");
//填写服务器地址
m_wSocketID=m_hSocket;
SOCKADDR_IN SocketAddr;
memset(&SocketAddr,0,sizeof(SocketAddr));
SocketAddr.sin_family=AF_INET;
SocketAddr.sin_port=htons(wPort);
SocketAddr.sin_addr.S_un.S_addr=dwServerIP;
//连接服务器
int iErrorCode=0;
WSASetLastError(0);
//if (m_ProxyInfo.cbProxyType!=PROXY_NONE)
//{
// throw TEXT("未支持代理服务器");
//}
//else
{
//绑定窗口
iErrorCode=WSAAsyncSelect(m_hSocket,m_hWnd,WM_SOCKET_NOTIFY,FD_READ|FD_CONNECT|FD_CLOSE);
if (iErrorCode==SOCKET_ERROR) throw TEXT("绑定内部窗口错误");
//连接服务器
iErrorCode=connect(m_hSocket,(SOCKADDR *)&SocketAddr,sizeof(SocketAddr));
if (iErrorCode==SOCKET_ERROR)
{
iErrorCode=WSAGetLastError();
if (iErrorCode!=WSAEWOULDBLOCK)
{
static TCHAR szBuffer[64];
_sntprintf(szBuffer,sizeof(szBuffer),TEXT("连接发生错误,错误代码 [ %d ]"),iErrorCode);
throw szBuffer;
}
}
//设置变量
m_cbSocketStatus=SOCKET_STATUS_WAIT;
}
return CONNECT_SUCCESS;
}
catch (LPCTSTR pszError)
{
CloseSocket();
throw pszError;
return CONNECT_FAILURE;
}
catch (...)
{
CloseSocket();
throw TEXT("连接产生未知异常错误");
return CONNECT_EXCEPTION;
}
}
//连接服务器
BYTE CClientSocket::Connect(const LPCTSTR pszServerIP, WORD wPort)
{
//效验数据
ASSERT(wPort!=0);
ASSERT(pszServerIP!=NULL);
if ((pszServerIP==NULL)||(wPort==0)) return false;
return Connect(TranslateAddr(pszServerIP),wPort);
}
//发送函数
WORD CClientSocket::SendData(WORD wMainCmdID, WORD wSubCmdID)
{
//效验状态
if (m_hSocket==INVALID_SOCKET) return false;
if (m_cbSocketStatus!=SOCKET_STATUS_CONNECT) return false;
//构造数据
BYTE cbDataBuffer[SOCKET_TCP_BUFFER];
TCP_Head * pHead=(TCP_Head *)cbDataBuffer;
pHead->CommandInfo.wMainCmdID=wMainCmdID;
pHead->CommandInfo.wSubCmdID=wSubCmdID;
//加密数据
WORD wSendSize = EncryptBuffer(cbDataBuffer, sizeof(TCP_Head), sizeof(cbDataBuffer));
m_dwSendPacketCount++;
//发送数据
return (WORD)SendDataBuffer(cbDataBuffer,wSendSize);
}
//发送函数
WORD CClientSocket::SendData(WORD wMainCmdID, WORD wSubCmdID, VOID * pData, WORD wDataSize)
{
//效验状态
if (m_hSocket==INVALID_SOCKET) return false;
if (m_cbSocketStatus!=SOCKET_STATUS_CONNECT) return false;
//效验大小
ASSERT(wDataSize<=SOCKET_TCP_PACKET);
if (wDataSize>SOCKET_TCP_PACKET) return false;
//构造数据
BYTE cbDataBuffer[SOCKET_TCP_BUFFER];
TCP_Head * pHead=(TCP_Head *)cbDataBuffer;
pHead->CommandInfo.wMainCmdID=wMainCmdID;
pHead->CommandInfo.wSubCmdID=wSubCmdID;
if (wDataSize>0)
{
ASSERT(pData!=NULL);
CopyMemory(pHead+1,pData,wDataSize);
}
//加密数据
WORD wSendSize = EncryptBuffer(cbDataBuffer, sizeof(TCP_Head) + wDataSize, sizeof(cbDataBuffer));
m_dwSendPacketCount++;
//发送数据
return (WORD)SendDataBuffer(cbDataBuffer, wSendSize);
}
//关闭连接
void CClientSocket::CloseSocket()
{
//关闭连接
bool bClose=(m_hSocket!=INVALID_SOCKET);
m_cbSocketStatus=SOCKET_STATUS_IDLE;
if (m_hSocket!=INVALID_SOCKET)
{
WSAAsyncSelect(m_hSocket,GetSafeHwnd(),WM_SOCKET_NOTIFY,0);
closesocket(m_hSocket);
m_hSocket=INVALID_SOCKET;
m_cbSocketStatus=SOCKET_STATUS_IDLE;
}
if ((bClose == true) && (m_pIClientSocketSink != NULL))
{
ASSERT(m_pIClientSocketSink != NULL);
try { m_pIClientSocketSink->OnEventClientSocketShut(m_wSocketID, SHUT_REASON_NORMAL); }
catch (...) {}
}
//恢复数据
m_wRecvSize=0;
m_cbSendRound=0;
m_cbRecvRound=0;
m_dwSendXorKey=0;
m_dwRecvXorKey=0;
m_dwSendTickCount=0;
m_dwRecvTickCount=0;
m_dwSendPacketCount=0;
m_dwRecvPacketCount=0;
return;
}
//发送数据
DWORD CClientSocket::SendDataBuffer(void * pBuffer, WORD wSendSize)
{
//效验参数
ASSERT(wSendSize!=0);
ASSERT(pBuffer!=NULL);
//发送数据
WORD wSended=0;
while (wSended<wSendSize)
{
int iErrorCode=send(m_hSocket,(char *)pBuffer+wSended,wSendSize-wSended,0);
if (iErrorCode==SOCKET_ERROR)
{
if (WSAGetLastError()==WSAEWOULDBLOCK)
{
m_dwSendTickCount=GetTickCount()/1000L;
return true;
}
return false;
}
wSended+=iErrorCode;
}
m_dwSendTickCount=GetTickCount()/1000L;
return true;
}
//解释服务器地址
DWORD CClientSocket::TranslateAddr(LPCTSTR pszServerAddr)
{
//转化地址
DWORD dwServerIP=inet_addr((LPCSTR)CT2A(pszServerAddr));
if (dwServerIP==INADDR_NONE)
{
LPHOSTENT lpHost=gethostbyname((LPCSTR)CT2A(pszServerAddr));
if (lpHost==NULL) return INADDR_NONE;
dwServerIP=((LPIN_ADDR)lpHost->h_addr)->s_addr;
}
return dwServerIP;
}
//解释错误
/*LPCTSTR CClientSocket::GetConnectError(int iErrorCode, LPTSTR pszBuffer, WORD wBufferSize)
{
//效验参数
ASSERT(pszBuffer!=NULL);
if (pszBuffer==NULL) return NULL;
//解释错误
switch (iErrorCode)
{
case 0: //没有错误
{
lstrcpyn(pszBuffer,TEXT("操作执行成功"),wBufferSize);
break;
}
case WSAEADDRNOTAVAIL: //地址格式错误
{
lstrcpyn(pszBuffer,TEXT("目标服务器地址格式不正确,请检查后再次尝试!"),wBufferSize);
break;
}
case WSAECONNREFUSED: //服务器没有启动
{
lstrcpyn(pszBuffer,TEXT("目标服务器繁忙或者没有启动!"),wBufferSize);
break;
}
case WSAETIMEDOUT: //连接超时
{
lstrcpyn(pszBuffer,TEXT("连接超时,可能是目标服务器不存在或者服务器地址格式不正确!"),wBufferSize);
break;
}
case WSAEHOSTUNREACH:
{
lstrcpyn(pszBuffer,TEXT("网络连接失败,请检查是否已经成功拨号和连接 Internet "),wBufferSize);
break;
}
default: //默认错误
{
_snprintf(pszBuffer,wBufferSize,TEXT("连接错误号:%ld详细错误信息请参考操作帮助手册"),iErrorCode);
break;
}
}
return pszBuffer;
}*/
//网络连接
LRESULT CClientSocket::OnSocketNotifyConnect(WPARAM wParam, LPARAM lParam)
{
//判断状态
int iErrorCode=WSAGETSELECTERROR(lParam);
if (iErrorCode==0) m_cbSocketStatus=SOCKET_STATUS_CONNECT;
else CloseSocket();
//发送通知
//TCHAR szErrorDesc[128]=TEXT("");
//GetConnectError(iErrorCode,szErrorDesc,sizeof(szErrorDesc));
m_pIClientSocketSink->OnEventClientSocketLink(m_wSocketID, iErrorCode);
return 1;
}
//网络读取
LRESULT CClientSocket::OnSocketNotifyRead(WPARAM wParam, LPARAM lParam)
{
try
{
//读取数据
int iRetCode=recv(m_hSocket,(char *)m_cbRecvBuf+m_wRecvSize,sizeof(m_cbRecvBuf)-m_wRecvSize,0);
if (iRetCode==SOCKET_ERROR) throw TEXT("网络连接关闭,读取数据失败");
ASSERT(m_dwSendPacketCount>0);
m_wRecvSize+=iRetCode;
m_dwRecvTickCount=GetTickCount()/1000L;
//变量定义
WORD wPacketSize=0;
BYTE cbDataBuffer[SOCKET_TCP_PACKET+sizeof(TCP_Head)];
TCP_Head * pHead=(TCP_Head *)m_cbRecvBuf;
while (m_wRecvSize>=sizeof(TCP_Head))
{
//效验参数
wPacketSize=pHead->TCPInfo.wPacketSize;
ASSERT(pHead->TCPInfo.cbDataKind == DK_MAPPED);
ASSERT(wPacketSize<=(SOCKET_TCP_PACKET+sizeof(TCP_Head)));
if (pHead->TCPInfo.cbDataKind != DK_MAPPED) throw TEXT("数据包版本错误");
if (wPacketSize>(SOCKET_TCP_PACKET+sizeof(TCP_Head))) throw TEXT("数据包太大");
if (m_wRecvSize<wPacketSize) return 1;
//拷贝数据
m_dwRecvPacketCount++;
CopyMemory(cbDataBuffer,m_cbRecvBuf,wPacketSize);
m_wRecvSize-=wPacketSize;
MoveMemory(m_cbRecvBuf,m_cbRecvBuf+wPacketSize,m_wRecvSize);
//解密数据
WORD wRealySize = CrevasseBuffer(cbDataBuffer, wPacketSize);
ASSERT(wRealySize>=sizeof(TCP_Head));
//解释数据
WORD wDataSize=wRealySize-sizeof(TCP_Head);
void * pDataBuffer=cbDataBuffer+sizeof(TCP_Head);
TCP_Command Command=((TCP_Head *)cbDataBuffer)->CommandInfo;
//内核命令
if (Command.wMainCmdID==MDM_KN_COMMAND)
{
switch (Command.wSubCmdID)
{
case SUB_KN_DETECT_SOCKET: //网络检测
{
//发送数据
SendData(MDM_KN_COMMAND,SUB_KN_DETECT_SOCKET,pDataBuffer,wDataSize);
break;
}
}
continue;
}
//处理数据
bool bSuccess = m_pIClientSocketSink->OnEventClientSocketRead(m_wSocketID, Command, pDataBuffer, wDataSize);
if (bSuccess==false) throw TEXT("网络数据包处理失败");
};
}
catch (...)
{
CloseSocket();
}
return 1;
}
//网络关闭
LRESULT CClientSocket::OnSocketNotifyClose(WPARAM wParam, LPARAM lParam)
{
//m_cbSocketStatus=SHUT_REASON_NORMAL;
CloseSocket();
return 1;
}
//映射发送数据
BYTE CClientSocket::MapSendByte(BYTE const cbData)
{
BYTE cbMap = g_SendByteMap[cbData];
return cbMap;
}
//映射接收数据
BYTE CClientSocket::MapRecvByte(BYTE const cbData)
{
BYTE cbMap = g_RecvByteMap[cbData];
return cbMap;
}
//加密数据
WORD CClientSocket::EncryptBuffer(BYTE pcbDataBuffer[], WORD wDataSize, WORD wBufferSize)
{
int i = 0;
//效验参数
ASSERT(wDataSize >= sizeof(TCP_Head));
ASSERT(wBufferSize >= (wDataSize + 2 * sizeof(DWORD)));
ASSERT(wDataSize <= (sizeof(TCP_Head) + SOCKET_TCP_BUFFER));
//调整长度
WORD wEncryptSize = wDataSize - sizeof(TCP_Command), wSnapCount = 0;
if ((wEncryptSize % sizeof(DWORD)) != 0)
{
wSnapCount = sizeof(DWORD) - wEncryptSize % sizeof(DWORD);
memset(pcbDataBuffer + sizeof(TCP_Info) + wEncryptSize, 0, wSnapCount);
}
//效验码与字节映射
BYTE cbCheckCode = 0;
for (WORD i = sizeof(TCP_Info); i < wDataSize; i++)
{
cbCheckCode += pcbDataBuffer[i];
pcbDataBuffer[i] = MapSendByte(pcbDataBuffer[i]);
}
//填写信息头
TCP_Head * pHead = (TCP_Head *)pcbDataBuffer;
pHead->TCPInfo.cbCheckCode = ~cbCheckCode + 1;
pHead->TCPInfo.wPacketSize = wDataSize;
pHead->TCPInfo.cbDataKind = DK_MAPPED;
//设置变量
m_dwSendPacketCount++;
return wDataSize;
}
//解密数据
WORD CClientSocket::CrevasseBuffer(BYTE pcbDataBuffer[], WORD wDataSize)
{
//效验参数
ASSERT(m_dwSendPacketCount > 0);
ASSERT(wDataSize >= sizeof(TCP_Head));
ASSERT(((TCP_Head *)pcbDataBuffer)->TCPInfo.wPacketSize == wDataSize);
//调整长度
WORD wSnapCount = 0;
if ((wDataSize % sizeof(DWORD)) != 0)
{
wSnapCount = sizeof(DWORD) - wDataSize % sizeof(DWORD);
memset(pcbDataBuffer + wDataSize, 0, wSnapCount);
}
//效验码与字节映射
TCP_Head * pHead = (TCP_Head *)pcbDataBuffer;
BYTE cbCheckCode = pHead->TCPInfo.cbCheckCode;
for (int i = sizeof(TCP_Info); i < wDataSize; i++)
{
pcbDataBuffer[i] = MapRecvByte(pcbDataBuffer[i]);
cbCheckCode += pcbDataBuffer[i];
}
//if (cbCheckCode != 0)
//{
// ZASSERT_R(0);
// throw TEXT("数据包效验码错误");
//}
return wDataSize;
}
//SOCKET 消息处理程序
LRESULT CClientSocket::OnSocketNotify(WPARAM wParam, LPARAM lParam)
{
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT: //网络连接
{
return OnSocketNotifyConnect(wParam,lParam);
}
case FD_READ: //数据读取
{
return OnSocketNotifyRead(wParam,lParam);
}
case FD_CLOSE: //网络关闭
{
return OnSocketNotifyClose(wParam,lParam);
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
//建立对象函数
DECLARE_CREATE_MODULE(ClientSocket)
//////////////////////////////////////////////////////////////////////////