📄 sockettraffic.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 + -