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

📄 networkthread.cpp

📁 vc6.0是一个很好的开放环境
💻 CPP
字号:
// NetWorkThread.cpp: implementation of the CNetWorkThread class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ChenMiddleware.h"
#include "NetWorkThread.h"
#include "Get_CheckSum.h"
#include "DataBase.h"


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

#define PACKETlEN_FIELD_VALUE 4
#define PROTOCAL_FIELD_VALUE 4

CDB g_db;

extern HANDLE g_hEventEnd;
extern bool bThreadExitFlag;
extern char g_ServerIp[16];
extern int g_ListenPort;
extern CStatic	*g_Static_Tishi1;
extern CListCtrl *g_pListBox_Main;
extern CGetCheckSum g_CheckSum;

WSAEVENT g_eventArray[WSA_MAXIMUM_WAIT_EVENTS]; //存放事件对象全局数组
SOCKET g_sockArray[WSA_MAXIMUM_WAIT_EVENTS];  //存放Socket句柄的数组
int g_nEventTotal = 0; //记录事件对象总数
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNetWorkThread::CNetWorkThread()
{

}

CNetWorkThread::~CNetWorkThread()
{

}

bool CNetWorkThread::GetString(SOCKET hSocket, char *recBuf, int recBufSize)
{
	int ret,nLeft,idx,flag=1,icount=0;
	nLeft=recBufSize;
	idx=0;
	while(nLeft>0)
	{
        ret=recv(hSocket,&recBuf[idx],nLeft,0);
        if(ret==SOCKET_ERROR || ret==0 || ret==WSAETIMEDOUT) //套接字出错或者已经关闭或超时
		{
			flag=0;
			break;
		}
		idx+=ret;
		nLeft-=ret;
	}
	
    //返回判断
    if(flag==0)
	{
		TRACE1("recv errorcode: %d",ret);
		TRACE1("WSAGetLastError(): %d",WSAGetLastError());
		return false;
	}
	else
		//TRACE1("recv num: %d",ret);
		return true;
	
	//if no data arrives within the period specified in SO_RCVTIMEO 
	//the recv function returns WSAETIMEDOUT, 
	//and if data is received, recv returns SUCCESS.
}

bool CNetWorkThread::SendString(SOCKET m_hSocket, char *buf, int length)
{
	int nLeft,idx,ret,flag=1;
    nLeft=length;
	idx=0;
	while(nLeft>0) //确保完全发送出去
	{
		ret=send(m_hSocket,&buf[idx],nLeft,0);
		if(ret==SOCKET_ERROR)
		{
			flag=0;
			break;
		}
		nLeft-=ret;
		idx+=ret;
	}
	//返回判断
    if(flag==0)
		return false;
	else
		return true;
}

void CNetWorkThread::CreateThread()
{
	m_pThread=AfxBeginThread(ServiceFunction, this, THREAD_PRIORITY_NORMAL, 0, 0,  NULL );	
}

UINT CNetWorkThread::ServiceFunction(LPVOID pParam)
{
	//TRACE0("ServiceFunction(LPVOID pParam)");
	CNetWorkThread * pThread=(CNetWorkThread *)pParam;	
    pThread->Run();
	return 1;
}

int CNetWorkThread::Run()
{
    //TRACE0("CNetWorkThread::Run()");
	WSADATA wsa;
	m_hListen=NULL;
	WSAEVENT event0;
	char cHostName[255]="";
	char revbuf[1024]; //接收buf
	SYSTEMTIME stLocal;
	CString CurDateStr;
	sockaddr_in remoteAddr; 
	int nAddrLen = sizeof(remoteAddr);
	CString iItemStr;
	int iItemIndex=0;
	
	if(WSAStartup(MAKEWORD(2, 2), &wsa) == SOCKET_ERROR)
		return 1;
	if(LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wVersion) != 2)
		goto CLEANUP;

	if(::gethostname(cHostName,255)!=0)   //主机的机器名
	{
		MessageBox(NULL,"获取机器名出错!系统将关闭","警告",MB_ICONWARNING|MB_OK );
		return 0;
	}
	if(g_db.ConnectDB(cHostName,"STUDENTS","sa","00abcdly")==false)
	{
		MessageBox(NULL,"数据库连接失败","警告",MB_ICONWARNING|MB_OK );
		return 0;
	}
	TRACE0("数据库连接成功");
	
	SOCKADDR_IN sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = INADDR_ANY;//inet_addr(g_ServerIp);
	sockAddr.sin_port = htons(g_ListenPort);
	
	m_hListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(m_hListen == INVALID_SOCKET)
	{
		TRACE0("WSASocket: INVALID_SOCKET return");
		goto CLEANUP;
	}
	
	if(bind(m_hListen, (sockaddr*)&sockAddr, sizeof(sockAddr) ) == SOCKET_ERROR)
	{
		TRACE0("bind: Bind error");
		goto CLEANUP;
	}
	
	if(listen(m_hListen, 5) == SOCKET_ERROR)
	{
		TRACE0("Listen: listen error");
		goto CLEANUP;
	}
	TRACE0("Listen...");
	
	// 创建事件对象,并关联到新的套节字
	event0 = ::WSACreateEvent();
	::WSAEventSelect(m_hListen, event0, FD_ACCEPT|FD_CLOSE);
	// 添加到表中
	g_eventArray[g_nEventTotal] = event0;
	g_sockArray[g_nEventTotal] = m_hListen;	
	g_nEventTotal++;	
	
	while(1)
	{
		if(bThreadExitFlag==true)
		{
			bThreadExitFlag=false;
			TRACE0("正在停止服务...... ");
			for(int k=0;k<g_nEventTotal;k++)
			{
				closesocket(g_sockArray[k]);
				g_sockArray[k]=NULL;
			}
			WSACleanup();
			g_db.CloseDatabase();

			SetEvent(g_hEventEnd); //设置为有信号
			Sleep(10);
			return 0;
		}
		//在所有事件对象上等待, 正常返回第n号事件的顺序值,如0,1,2,...
		int nIndex = ::WSAWaitForMultipleEvents(g_nEventTotal, g_eventArray, FALSE, 10, FALSE);
		if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)
		{			
			continue;
		}
		//TRACE("nIndex1=%d",nIndex);
		// 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态
		nIndex = nIndex - WSA_WAIT_EVENT_0;
		for(int i=nIndex; i<g_nEventTotal; i++)
		{
			nIndex = ::WSAWaitForMultipleEvents(1, &g_eventArray[i], TRUE, 10, FALSE);
			if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)
			{
				continue;
			}
			else
			{
				//TRACE("nIndex2=%d",nIndex);
				// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
				WSANETWORKEVENTS event;
				::WSAEnumNetworkEvents(g_sockArray[i], g_eventArray[i], &event);
				if(event.lNetworkEvents & FD_ACCEPT)				// 处理FD_ACCEPT通知消息
				{
					if(event.iErrorCode[FD_ACCEPT_BIT] == 0)
					{
						if(g_nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)
						{
							TRACE0("Too many connections! ");
							continue;
						}
						SOCKET sNew = ::accept(g_sockArray[i], (SOCKADDR*)&remoteAddr, &nAddrLen);
						//这里可以加入身份认证,拒绝非法用户。
						
						::GetLocalTime(&stLocal);
						CurDateStr.Format("%u-%02u-%02u %02u:%02u:%02u", stLocal.wYear, stLocal.wMonth, stLocal.wDay,stLocal.wHour,stLocal.wMinute,stLocal.wSecond);
						if(g_pListBox_Main->GetItemCount()>=200)
						{
							g_pListBox_Main->DeleteAllItems();
							iItemIndex=0;
						}
						iItemStr.Format("%d",iItemIndex+1);
						g_pListBox_Main->InsertItem(iItemIndex,iItemStr);	
						g_pListBox_Main->SetItemText(iItemIndex,1,CurDateStr);
						g_pListBox_Main->SetItemText(iItemIndex,2,inet_ntoa(remoteAddr.sin_addr));
						//g_pListBox_Main->SetItemText(iItemIndex,3,"");
						iItemIndex++;

						WSAEVENT event = ::WSACreateEvent();
						::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);
						// 添加到表中
						g_eventArray[g_nEventTotal] = event;
						g_sockArray[g_nEventTotal] = sNew;	
						g_nEventTotal++;
					}
				}
				else if(event.lNetworkEvents & FD_READ)			// 处理FD_READ通知消息
				{
					if(event.iErrorCode[FD_READ_BIT] == 0)
					{
						//这里接收通信数据,解密,并处理。成功的话向客户返回消息。
						ZeroMemory(revbuf,1024);
						int iPacetLength;
						char cRet;
						char sendbuf[11]="#*********";
						bool nRecv1=false,nRecv2=false;
						char NewCheckSum[9]="",OldCheckSum[9]="";
						char protocal[PROTOCAL_FIELD_VALUE+1]="";

						nRecv1 =GetString(g_sockArray[i], revbuf,PACKETlEN_FIELD_VALUE);
						if(nRecv1)				
						{
							revbuf[PACKETlEN_FIELD_VALUE]=0;
							iPacetLength=atoi(revbuf);
							TRACE1("接收到数据头部长度字段: %d",iPacetLength);
							nRecv2=GetString(g_sockArray[i], revbuf+PACKETlEN_FIELD_VALUE, iPacetLength-PACKETlEN_FIELD_VALUE);
						    if(nRecv2)
							{
								TRACE1("接收到数据:%s", revbuf);

								//NO1: 得到传过来的原始校验和值
								strncpy(OldCheckSum,revbuf+iPacetLength-8,8);
								OldCheckSum[8]=0;

								//NO2: 计算校验和,并检验
                                g_CheckSum.Get_CheckSum(revbuf,iPacetLength,NewCheckSum);
								
								TRACE2("OldCheckSum=%s,NewCheckSum=%s",OldCheckSum,NewCheckSum);
								if(strcmp(NewCheckSum,OldCheckSum)!=0)
									cRet='3'; //校验和错误
								else
								{
									strncpy(protocal,revbuf+PACKETlEN_FIELD_VALUE,PROTOCAL_FIELD_VALUE);//提取协议字段值
									protocal[PROTOCAL_FIELD_VALUE]=0;
									cRet=DoPacket(protocal,revbuf+PACKETlEN_FIELD_VALUE+PROTOCAL_FIELD_VALUE,iPacetLength-PACKETlEN_FIELD_VALUE-PROTOCAL_FIELD_VALUE);
								}
								
								//构造返回数据,生成校验并发送
								sendbuf[0]=cRet;
								g_CheckSum.Get_CheckSum(sendbuf,strlen(sendbuf),NewCheckSum);
								
								SendString(g_sockArray[i],sendbuf,10);								
							}
							
						}
					    if(nRecv1==false || nRecv2==false) //nRecv= 0 or SOCKET_ERROR 
						{
							TRACE0("beacuse: nRecv= 0 or SOCKET_ERROR. so call: closesocket,WSACloseEvent");
							::closesocket(g_sockArray[i]);
							WSACloseEvent(g_eventArray[i]);
							for(int j=i; j<g_nEventTotal-1; j++)
							{
								g_eventArray[j] = g_eventArray[j+1];
								g_sockArray[j] = g_sockArray[j+1];	
							}
							g_nEventTotal--;							
						}
					}

				}//end else if
				else if(event.lNetworkEvents & FD_CLOSE)		// 处理FD_CLOSE通知消息
				{					
					TRACE0("FD_CLOSE: closesocket,WSACloseEvent");
					::closesocket(g_sockArray[i]);
					WSACloseEvent(g_eventArray[i]);
					for(int j=i; j<g_nEventTotal-1; j++)
					{
						g_eventArray[j] = g_eventArray[j+1];
						g_sockArray[j] = g_sockArray[j+1];	
					}
					g_nEventTotal--;					
				}
				else if(event.lNetworkEvents & FD_WRITE)		// 处理FD_WRITE通知消息
				{
					TRACE0("FD_WRITE通知消息,有客户进入");
				}			
				
			}
			
		}//end for   
	}//end while(1)
	
CLEANUP:
	if(m_hListen != NULL)  //关掉监听socket
	{
		closesocket(m_hListen);
		m_hListen=NULL;
	}
	g_Static_Tishi1->SetWindowText(" 警告:启动失败. 请点击‘停止服务’按钮!");
	WSACleanup();
	TRACE0("未启动");
	return 1;
}

//处理请求包
char CNetWorkThread::DoPacket(char portocalchar[], char packet[], int iPacketLen)
{
	char ret;
	switch (atoi(portocalchar))
	{
	case 1:
	    ret=m_DopacketObj.AddStudents(packet,iPacketLen);
		break;
	case 2:
		break;
	}	
	return ret;
}


⌨️ 快捷键说明

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