⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clientsock.cpp

📁 基于dialogic语音卡的IVR系统源代码
💻 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 + -