📄 clientsock.cpp
字号:
// ClientSock.cpp : implementation file
//
#include "stdafx.h"
#include "ClientSock.h"
#include "Setup.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CClientSock
CClientSock::CClientSock(PPROCESSRCVPACKET pProcessRcvPacket)
{
m_lAllEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE;
m_iRcvState = 0; //首先接收包头
m_szPacketHeader = NULL;
m_szPacketData = NULL;
m_iRcvedLen_PacketHeader = 0;
m_iRcvedLen_PacketData = 0;
m_iLen_DataField = 0;
m_bRcvDone = FALSE;
m_iDefinedLen_PacketHeader = sizeof(struct Header_Comm);
m_pProcessRcvPacketFunc = pProcessRcvPacket;
}
CClientSock::~CClientSock()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CClientSock, CSocket)
//{{AFX_MSG_MAP(CClientSock)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CClientSock member functions
void CClientSock::OnReceive(int nErrorCode)
{
//防止OnReceive重入
AsyncSelect(m_lAllEvent ^ FD_READ);
int iReceivedLen = 0;
char aszTempBuf[9*1024];
iReceivedLen = Receive(aszTempBuf, sizeof(aszTempBuf));
if(iReceivedLen == SOCKET_ERROR)
{
AfxMessageBox("SOCKET_ERROR");
goto HERE;
}
if(m_iRcvState == 0)
{//正在接收包头
if(AddToHeader(aszTempBuf, iReceivedLen) != 0)
{
AfxMessageBox("Receive Header error");
ProcessRcvError();
goto HERE;
}
}
else
{//正在接收数据域
if(AddToDataField(aszTempBuf, iReceivedLen) != 0)
{
AfxMessageBox("Receive Data Field error");
ProcessRcvError();
goto HERE;
}
}
HERE:
CSocket::OnReceive(nErrorCode);
//允许OnReceive
AsyncSelect(m_lAllEvent);
}
void CClientSock::OnClose(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
DWORD dwThreadID = GetCurrentThreadId();
PostThreadMessage(dwThreadID, WM_SOCK_CLOSED, 0, 0);
//要在这里CLOSE(),避免以后再次发生ONCLOSE()
Close();
CSocket::OnClose(nErrorCode);
}
int CClientSock::AddToHeader(char *szRcvedData, int iLength)
{
/************************************************************
三种情况
1.迄今收到的数据正好等于包头长度,完成包头的接收,开始接收DATA
2.迄今收到的数据大于包头长度,需要分成HEADER和DATA两部分处理,
如果DATA不够,继续接收DATA;如果DATA足够,接收完DATA后,开始接收
下一个包头
3.迄今收到的数据小于包头长度,填充包头,还要继续接收包头
************************************************************/
int iRcvedLen_LastTime = m_iRcvedLen_PacketHeader;
int iLenLeft_Header = m_iDefinedLen_PacketHeader - iRcvedLen_LastTime;
m_iRcvedLen_PacketHeader += iLength;
if(m_szPacketHeader == NULL)
{
m_szPacketHeader = (char *)malloc(m_iDefinedLen_PacketHeader);
}
if(m_iRcvedLen_PacketHeader == m_iDefinedLen_PacketHeader)
{//迄今收到的数据长度正好等于包头长度
memcpy(m_szPacketHeader + iRcvedLen_LastTime,
szRcvedData,
iLength);
m_iLen_DataField = GetDataFieldLen(m_szPacketHeader, m_iDefinedLen_PacketHeader);
if(m_iLen_DataField == -1)
{
return -1;
}
m_iRcvState = 1; //下一步就接收数据域
goto HERE;
}
if(m_iRcvedLen_PacketHeader < m_iDefinedLen_PacketHeader)
{//迄今收到的数据长度仍然小于包头长度
memcpy(m_szPacketHeader + iRcvedLen_LastTime,
szRcvedData,
iLength);
//继续接收数据域,m_iRcvState状态不变
}
if(m_iRcvedLen_PacketHeader > m_iDefinedLen_PacketHeader)
{//迄今收到的数据长度大于包头长度,要分别放到HEADER和DATA中
//将前部分接收数据放到HEADER中
memcpy(m_szPacketHeader + iRcvedLen_LastTime,
szRcvedData,
iLenLeft_Header);
m_iLen_DataField = GetDataFieldLen(m_szPacketHeader, m_iDefinedLen_PacketHeader);
if(m_iLen_DataField == -1)
{
return -1;
}
//将后部分接收数据放到DATA中
m_iRcvState = 1;
if(AddToDataField(szRcvedData + iLenLeft_Header,
iLength - iLenLeft_Header) != 0)
{
return -1;
}
}
HERE:
return 0;
}
int CClientSock::AddToDataField(char *szRcvedData, int iLength)
{
/************************************************************
三种情况
1.迄今收到的数据正好等于包数据段长度,完成包数据段的接收,开始接收HEADER
2.迄今收到的数据大于包数据段长度,按理不会发生,出错
3.迄今收到的数据小于包数据段长度,填充数据段,还要继续接收数据段
************************************************************/
int iRcvedLen_LastTime = m_iRcvedLen_PacketData;
int iLenLeft_DataField = m_iLen_DataField - iRcvedLen_LastTime;
m_iRcvedLen_PacketData += iLength;
if(m_szPacketData == NULL)
{
m_szPacketData = (char *)malloc(m_iLen_DataField);
if(m_szPacketData == NULL)
return -1;
}
if(m_iRcvedLen_PacketData > m_iLen_DataField)
{//这次接收的包中有下一个包的包头(可能还有包数据部分),在本机到本机的SOCKET通讯中曾经发生过(即说明在本机到本机的SOCKET通讯中,系统会把两次SEND()的数据放到一个TCP包中)。
//处理接收完的包的数据
memcpy(m_szPacketData + iRcvedLen_LastTime,
szRcvedData,
iLenLeft_DataField);
m_bRcvDone = TRUE;
ProcessRcvDone(m_szPacketData, m_iLen_DataField);
//处理下一个包
m_iRcvState = 0; ////设置状态,转为接收下一个包的包头
int iRcvedLen_NextPacket = iLength - iLenLeft_DataField;
char *szRcvedData_NextPacket = szRcvedData + iLenLeft_DataField;
if(AddToHeader(szRcvedData_NextPacket, iRcvedLen_NextPacket) != 0)
return -1;
return 0;
}
if(m_iRcvedLen_PacketData == m_iLen_DataField)
{//正好接收完这个数据段
memcpy(m_szPacketData + iRcvedLen_LastTime,
szRcvedData,
iLength);
m_bRcvDone = TRUE;
m_iRcvState = 0; //转为接收下一个包的包头
}
if(m_iRcvedLen_PacketData < m_iLen_DataField)
{//迄今收到的数据小于包数据段长度,填充数据段,还要继续接收数据段
memcpy(m_szPacketData + iRcvedLen_LastTime,
szRcvedData,
iLength);
//接收状态不变
}
if(m_bRcvDone)
{
ProcessRcvDone(m_szPacketData, m_iLen_DataField);
}
return 0;
}
int CClientSock::GetDataFieldLen(char *szHeader, int iLength)
{
if(iLength != sizeof(struct Header_Comm))
return -1;
struct Header_Comm *pheader_Comm = (struct Header_Comm *)szHeader;
return pheader_Comm->uiLength;
}
int CClientSock::ProcessRcvError()
{
//接收包出错时,采用全部置0,从接收包头开始
BeginNewPacket();
return 0;
}
int CClientSock::BeginNewPacket()
{
m_iRcvState = 0; //首先接收包头
m_iRcvedLen_PacketHeader = 0;
m_iRcvedLen_PacketData = 0;
m_iLen_DataField = 0;
m_bRcvDone = FALSE;
if(m_szPacketHeader != NULL)
{
free(m_szPacketHeader);
m_szPacketHeader = NULL;
}
if(m_szPacketData != NULL)
{
free(m_szPacketData);
m_szPacketData = NULL;
}
return 0;
}
int CClientSock::ProcessRcvDone(char *szPacket, int iPacketLen)
{
/***********************************************]
功能: 处理收到的完整包
***********************************************/
if(m_bRcvDone)
{
m_pProcessRcvPacketFunc(szPacket, iPacketLen, this);
//释放工作
BeginNewPacket();
}
else
return -1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -