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

📄 sockettraffic.cpp

📁 上位机vc6.0编程控制西门子GPRS模块实现短信收发
💻 CPP
字号:
// SocketTraffic.cpp: implementation of the CSocketTraffic class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GrpsTest.h"
#include "SocketTraffic.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSocketTraffic::CSocketTraffic()
{
	m_nSendIn = 0;
	m_nSendOut = 0;
	m_nRecvIn = 0;
	m_nRecvOut = 0;
	m_nConnectIn = 0;
	m_nConnectOut = 0;
	m_nCloseIn = 0;
	m_nCloseOut = 0;
	m_bThreadStatus = FALSE;		// 线程默认为挂起状态
	m_bThreadWait = TRUE;

	m_hKillThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);		// 创建一个手动重置的事件
	m_hThreadKilledEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_hThreadRunEvent = CreateEvent(NULL,FALSE,FALSE,NULL);		// 创建一个手动重置的事件,事件初始状态为无信号状态

	InitializeCriticalSection(&m_csSend);
	InitializeCriticalSection(&m_csRecv);
	InitializeCriticalSection(&m_csConnect);
	InitializeCriticalSection(&m_csClose);
	AfxBeginThread(SocketThread, this, THREAD_PRIORITY_NORMAL);
}

CSocketTraffic::~CSocketTraffic()
{
	SetEvent(m_hThreadRunEvent);
	SetEvent(m_hKillThreadEvent);
	WaitForSingleObject(m_hThreadKilledEvent,INFINITE);
	
	DeleteCriticalSection(&m_csSend);
	DeleteCriticalSection(&m_csRecv);
	DeleteCriticalSection(&m_csConnect);
	DeleteCriticalSection(&m_csClose);

	CloseHandle(m_hKillThreadEvent);
	CloseHandle(m_hThreadKilledEvent);
}

void CSocketTraffic::PutConnectSocket(SOCKET_PARAM* pSocketParam)
{
	EnterCriticalSection(&m_csConnect);
	memcpy(&m_ConnectSocket[m_nConnectIn], pSocketParam, sizeof(SOCKET_PARAM));
	m_nConnectIn++;
	if (m_nConnectIn >= MAX_SM_SEND)  m_nConnectIn = 0;

	LeaveCriticalSection(&m_csConnect);
}

BOOL CSocketTraffic::GetConnectSocket(SOCKET_PARAM* pSocketParam)
{
	BOOL fSuccess = FALSE;
	EnterCriticalSection(&m_csConnect);
	if (m_nConnectOut != m_nConnectIn)
	{
		memcpy(pSocketParam, &m_ConnectSocket[m_nSendOut], sizeof(SOCKET_PARAM));
		m_nConnectOut++;
		if (m_nConnectOut >= MAX_SM_SEND)  m_nConnectOut = 0;
		fSuccess = TRUE;
	}
	LeaveCriticalSection(&m_csConnect);
	return fSuccess;
}

void CSocketTraffic::PutCloseSocket(SOCKET_PARAM* pSocketParam)
{
	EnterCriticalSection(&m_csClose);
	memcpy(&m_CloseSocket[m_nCloseIn],pSocketParam,sizeof(SOCKET_PARAM));
	m_nCloseIn++;
	if (m_nCloseIn>=MAX_SM_SEND) m_nCloseIn = 0;
	LeaveCriticalSection(&m_csClose);
}

BOOL CSocketTraffic::GetCloseSocket(SOCKET_PARAM* pSocketParam)
{
	BOOL fSuccess = FALSE;
	EnterCriticalSection(&m_csClose);
	if (m_nCloseOut!=m_nCloseIn)
	{
		memcpy(pSocketParam,&m_CloseSocket[m_nCloseOut],sizeof(SOCKET_PARAM));
		m_nCloseOut++;
		if (m_nCloseOut>=MAX_SM_SEND) m_nCloseOut = 0;
		fSuccess = TRUE;
	}
	LeaveCriticalSection(&m_csClose);
	return fSuccess;
}

void CSocketTraffic::PutSendData(SOCKETDATA_PARAM* pSocketParam)
{
	EnterCriticalSection(&m_csSend);
	memcpy(&m_SocketSend[m_nSendIn], pSocketParam, sizeof(SOCKETDATA_PARAM));
	m_nSendIn++;
	if (m_nSendIn >= MAX_SM_SEND)  m_nSendIn = 0;
	LeaveCriticalSection(&m_csSend);
}

BOOL CSocketTraffic::GetSendData(SOCKETDATA_PARAM* pSocketParam)
{
	BOOL fSuccess = FALSE;
	EnterCriticalSection(&m_csSend);
	if (m_nSendOut!=m_nSendIn)
	{
		memcpy(pSocketParam,&m_SocketSend[m_nSendOut],sizeof(SOCKETDATA_PARAM));
		m_nSendOut++;
		if (m_nSendOut>=MAX_SM_SEND) m_nSendOut = 0;
		fSuccess = TRUE;
	}
	LeaveCriticalSection(&m_csSend);
	return fSuccess;
}

void CSocketTraffic::PutRecvData(SOCKETDATA_PARAM* pSocketParam, int nCount)
{
	EnterCriticalSection(&m_csRecv);
	for (int i = 0; i < nCount; i++)
	{
		memcpy(&m_SocketRecv[m_nRecvIn], pSocketParam, sizeof(SM_PARAM));
	
		m_nRecvIn++;
		if (m_nRecvIn >= MAX_SM_RECV)  m_nRecvIn = 0;

		pSocketParam++;
	}

	LeaveCriticalSection(&m_csRecv);

}

BOOL CSocketTraffic::GetRecvData(SOCKETDATA_PARAM* pSocketParam)
{
	BOOL fSuccess = FALSE;
	EnterCriticalSection(&m_csRecv);
	if (m_nRecvOut != m_nRecvIn)
	{
		memcpy(pSocketParam, &m_SocketRecv[m_nRecvOut], sizeof(SM_PARAM));

		m_nRecvOut++;
		if (m_nRecvOut >= MAX_SM_RECV)  m_nRecvOut = 0;

		fSuccess = TRUE;
	}
	LeaveCriticalSection(&m_csRecv);
	return fSuccess;
}

void CSocketTraffic::SetThreadStatus(BOOL status)
{
	if (status==TRUE)
	{
		m_bThreadStatus = TRUE;
		m_bThreadWait = FALSE;
		SetEvent(m_hThreadRunEvent);
	}
	else
	{
		m_bThreadStatus = FALSE;
	}
}

BOOL CSocketTraffic::GetThreadStatus()
{
	return m_bThreadWait;
}
UINT CSocketTraffic::SocketThread(LPVOID lParam)
{
	CSocketTraffic* p=(CSocketTraffic *)lParam;	// this
	int ntimes;							// 发送不成功时重发次数
	int nSockets;						// 记录已经连接的socket数
	int nIndexSocket;					// 记录轮询缓冲区的socket索引
	int nData;							// 记录数据包的个数
	SOCKET_BUFF buff;					// 接收数据列表的缓冲区
	SOCKETDATA_PARAM dataparam[256];	// 发送/接收数据包缓冲区
	SOCKET_PARAM param[1];				// 连接/关闭socket缓冲区
	char *handle;						// 保存应答数据的指针
	CTime tmOrg, tmNow;					// 上次和现在的时间,计算超时用

	enum {
		stBeginRest,					// 开始休息/延时
		stContinueRest,					// 继续休息/延时
		stConnectSocketRequest,			// 建立Socket连接
		stConnectSocketResponse,	    // 读取已经建立socket连接的句柄
		stConnectSocketWaitIdle,	    // 建立连接不成功,等待回应
		stCloseSocketRequest,			// 关闭Socket连接
		stCloseSocketResponse,			// 读取关闭socket连接结果
		stCloseSocketWaitIdle,			// 关闭连接不成功,等待回应
		stSendDataRequest,				// 发送数据
		stSendDataResponse,				// 读取发送数据后GPRS返回值
		stSendDataWaitIdle,				// 发送不成功,等待GPRS就绪
		stReadDataRequest,				// 发送读取数据列表的命令
		stReadDataResponse,				// 读取数据列表到缓冲区
		stExitThread					// 退出
	} nState;							// 处理过程的状态

	nState = stBeginRest;

	while (nState != stExitThread)
	{
		if (p->m_bThreadStatus==FALSE&&nState==stBeginRest&&p->SocketBuffer.GetSize()==0)	// socket已经全部关闭完毕才真正地挂起该线程	
		{
			p->m_bThreadWait = TRUE;				// 线程已经被挂起
			ResetEvent(p->m_hThreadRunEvent);
		}
		else			SetEvent(p->m_hThreadRunEvent);			
		WaitForSingleObject(p->m_hThreadRunEvent,INFINITE);			// 等待事件发生
		switch(nState)
		{
			case stBeginRest:
				tmOrg = CTime::GetCurrentTime();
				nState = stContinueRest;
			break;
			case stContinueRest:
				Sleep(300);
				tmNow = CTime::GetCurrentTime();
				if (p->GetConnectSocket(param))				// 先判断缓冲区中是否有socket连接需要建立
				{
					nState = stConnectSocketRequest;
					ntimes = 0;
				}
				else if (p->GetSendData(&dataparam[0]))		// 判断缓冲区中是否有数据需要发送
				{
					nState = stSendDataRequest;
					ntimes = 0;
					nSockets = p->SocketBuffer.GetSize();
				}
				else if (p->GetCloseSocket(param))			// 判断缓冲区中是否有socket连接需要断开
				{
					nState = stCloseSocketRequest;
					ntimes = 0;
					nSockets = p->SocketBuffer.GetSize();
				}
				else if((tmNow-tmOrg)>4)					// 三秒钟发送缓冲区为空,则读取接收缓冲区的内容	
				{
					nState = stReadDataRequest;
					nIndexSocket = 0;						// 已经建立的从第0个索引开始读取数据
					nSockets = p->SocketBuffer.GetSize();
					if (nSockets<1) nState = stBeginRest;
				}
			
			break;
			case stConnectSocketRequest:
				ConnectSocket(param);
				memset(&buff, 0, sizeof(buff));
				tmOrg = CTime::GetCurrentTime();
				nState = stConnectSocketResponse;
			break;	
			case stConnectSocketResponse:
				Sleep(100);
				tmNow = CTime::GetCurrentTime();
				SocketGetResponse(&buff);
				handle = strstr(buff.data,"I/");
				if (handle)
				{
					if (strstr(buff.data,"ERROR"))			// 发送错误,重发
					{
						nState = stConnectSocketWaitIdle;	
					}	
					else
					{
						param[0].SOCKET_HANDLE[0] = handle[2];
						param[0].SOCKET_HANDLE[1] = handle[3];
						param[0].SOCKET_HANDLE[2] = handle[4];
						p->SocketBuffer.Add(param[0]);
						strcpy(dataparam[0].IP_ADDRESS,param[0].IP_ADDRESS);
						strcpy(dataparam[0].PORT_NUMBER,param[0].PORT_NUMBER);
						strcpy(dataparam[0].SOCKET_HANDLE,param[0].SOCKET_HANDLE);
						strcpy(dataparam[0].SEND_DATA,"CONNECTSUCCESS");
						p->PutRecvData(dataparam,1);		// 将接收到的socket句柄加入接收缓冲区中
						nState = stBeginRest;
					}
				}
				else
				{
					if ((tmNow-tmOrg)>90)					// 90秒内仍没有应答,则重发
					{
						nState = stConnectSocketWaitIdle;	
					}	
				}
			break;
			case stConnectSocketWaitIdle:					// 重发,直到成功为止
				Sleep(500);
				ntimes++;
				if(ntimes<3) 	nState = stConnectSocketRequest;	// 不到三次继续重发	
				else
				{
					strcpy(dataparam[0].SEND_DATA,"CONNFAIL");
					p->PutRecvData(dataparam,1);			// 通知主程序建立连接失败
					nState = stBeginRest;
				}
			break;
			case stSendDataRequest:
				SocketSendData(&dataparam[0]);
				memset(&buff, 0, sizeof(buff));
				tmOrg = CTime::GetCurrentTime();
				nState = stSendDataResponse;
			break;
			case stSendDataResponse:
				Sleep(100);
				tmNow = CTime::GetCurrentTime();
				SocketGetResponse(&buff);
				if (strstr(buff.data,"OK"))
				{
					strcpy(dataparam[0].SEND_DATA,"SENDSUCCESS");
					p->PutRecvData(dataparam,1);
					nState = stBeginRest;
				}
				else if (strstr(buff.data,"ERROR"))
				{
					nState = stSendDataWaitIdle;
				}
				else if((tmNow-tmOrg)>90)
				{
					nState = stSendDataWaitIdle;
				}
			break;
			case stSendDataWaitIdle:
				Sleep(500);
				ntimes++;
				if(ntimes<3) 	nState = stSendDataRequest;	// 不到三次继续重发	
				else
				{
					strcpy(dataparam[1].SEND_DATA,"SENDFAIL");
					p->PutRecvData(&dataparam[1],1);		// 通知主程序发送数据失败
					nState = stBeginRest;
				}
			break;
			case stCloseSocketRequest:
				CloseSocket(param);
				memset(&buff, 0, sizeof(buff));
				tmOrg = CTime::GetCurrentTime();
				nState = stCloseSocketResponse;
			break;
			case stCloseSocketResponse:
				Sleep(100);
				tmNow = CTime::GetCurrentTime();
				SocketGetResponse(&buff);
				if (strstr(buff.data,"DONE")||strstr(buff.data,"ONLINE"))	// socket关闭成功
				{
					strcpy(dataparam[0].SEND_DATA,"CLOSESUCCESS");
					for(int i=0;i<nSockets;i++)
					{
						if ((strcmp(p->SocketBuffer.GetAt(i).IP_ADDRESS,param[0].IP_ADDRESS)==0)&&
							(strcmp(p->SocketBuffer.GetAt(i).SOCKET_HANDLE,param[0].SOCKET_HANDLE))==0)
						{
							p->SocketBuffer.RemoveAt(i);
							break;		
						}
					}
					p->PutRecvData(dataparam,1);
					nState = stBeginRest;
				}
				else if (strstr(buff.data,"ERROR"))
				{
					nState = stCloseSocketWaitIdle;
				}
				else if ((tmNow-tmOrg)>90)
				{
					nState = stCloseSocketWaitIdle;
				}
			break;
			case stCloseSocketWaitIdle:
				Sleep(500);
				ntimes++;
				if(ntimes<3) 	nState = stCloseSocketRequest;	// 不到三次继续重发	
				else
				{
					strcpy(dataparam[0].SEND_DATA,"CLOSEFAIL");
					p->PutRecvData(dataparam,1);			// 通知主程序建立连接失败
					nState = stBeginRest;
				}
			break;
			default:
			break;
			case stReadDataRequest:
				if (nIndexSocket<nSockets)					// 判断是否轮询完毕
				{	
					SocketReadDataList(&(p->SocketBuffer.GetAt(nIndexSocket)));
					memset(&buff, 0, sizeof(buff));
					tmOrg = CTime::GetCurrentTime();
					nState = stReadDataResponse;
				}
				else										// 轮询socket完毕,返回初始状态
				{
					nState = stBeginRest;
				}
			break;
			case stReadDataResponse:
				Sleep(100);
				tmNow = CTime::GetCurrentTime();
				SocketGetResponse(&buff);						// 读取返回数据
				if(strstr(buff.data,"I/"))						// 成功返回,对数据进行处理
				{
					if(strstr(buff.data,"ERROR")==NULL)			// 如果没有出错,对数据进行处理
					{
						nData = SocketParseMessageList(&(p->SocketBuffer.GetAt(nIndexSocket)),dataparam,&buff);
						if(nData>0)									// 缓冲区中有数据
						{
							p->PutRecvData(dataparam,nData);
						}
					}
					nIndexSocket++;								// 无论是数据处理完毕还是出错,或是没有接收到任何数据,都轮询下一socket对象
					nState = stReadDataRequest;
				}
				else if ((tmNow-tmOrg)>90)						// 超过90秒仍没有应答,则认为出错,轮询下一socket对象
				{
					nIndexSocket++;
					nState = stReadDataRequest;
				}
			break;
		}
		DWORD dwEvent = WaitForSingleObject(p->m_hKillThreadEvent, 20);
		if (dwEvent == WAIT_OBJECT_0)  nState = stExitThread;
	}

	SetEvent(p->m_hThreadKilledEvent);
	
	return 9999;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -