www.pudn.com > dialogic_IVR.rar > 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; 
}