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

📄 tcpserver_ce.cpp

📁 EVC4.0入门程序 关于TCP测试使用工具
💻 CPP
字号:
// TCPServer_CE.cpp: implementation of the CTCPServer_CE class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Step3_tcptest.h"
#include "TCPServer_CE.h"

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

#include "TCPCustom_CE.h" 
#include <afxtempl.h>
//存储客户端Socket句柄
//CList<CTCPCustom_CE,CTCPCustom_CE&> m_ListClientSocket;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//构造函数
CTCPServer_CE::CTCPServer_CE()
{
	//创建线程退出事件句柄
	m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
	m_pTCPConnect = new CTCPCustom_CE( );
}

//析构函数
CTCPServer_CE::~CTCPServer_CE()
{
	//关闭线程退出事件句柄
	CloseHandle(m_exitThreadEvent);
	if( m_pTCPConnect->m_bSocketEnable )
		m_pTCPConnect->Close( );
	delete m_pTCPConnect;
}

/*--------------------------------------------------------------------
【函数介绍】:  此线程用于检测监听套接字事件。
【入口参数】:  lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。
			   在这里我们将CTCPServer_CE类实例指针传进来
【出口参数】:  (无)
【返回  值】:  返回值没有特别的意义,在此我们将返回值设为0。
---------------------------------------------------------------------*/
DWORD CTCPServer_CE::SocketListenThread(PVOID lparam)
{
	CTCPServer_CE *pSocket;
	//得到CTCPServer_CE实例指针
	pSocket = (CTCPServer_CE*)lparam;
	//定义读事件集合
	fd_set fdRead;
	int ret;
	TIMEVAL	aTime;
	aTime.tv_sec = 1;
	aTime.tv_usec = 1;
	while (TRUE)
	{
        //收到退出事件,结束线程
		if (WaitForSingleObject(pSocket->m_exitThreadEvent,0) == WAIT_OBJECT_0)
		{
			break;
		}
		
		FD_ZERO(&fdRead);
		FD_SET(pSocket->m_ServerSocket,&fdRead);
		
		ret = select(0,&fdRead,NULL,NULL,&aTime);
		
		if (ret == SOCKET_ERROR)
		{
			//触发错误事件
			int iErrorCode = WSAGetLastError();
			//触发socket的错误事件
			pSocket->OnError(pSocket->m_pOwnerWnd, iErrorCode);
			//关闭服务器套接字 
			closesocket(pSocket->m_ServerSocket);
			break;
		}
		
		if (ret > 0)
		{
			//判断是否读事件
			if (FD_ISSET(pSocket->m_ServerSocket,&fdRead))
			{
				//如果调用了Listen,则表示触发了OnAccept事件
				if( pSocket->m_pTCPConnect->m_bSocketEnable )
				{
					pSocket->OnClose( pSocket->m_pOwnerWnd );
					pSocket->m_pTCPConnect->Close( );
					pSocket->m_pTCPConnect->m_bSocketEnable = FALSE;
				}

		    	SOCKADDR_IN clientAddr;
				//CTCPCustom_CE * pClientSocket = new CTCPCustom_CE();
				int namelen = sizeof(clientAddr);
				//等待,创建与客户端连接的套接字
				pSocket->m_pTCPConnect->m_socket = accept(pSocket->m_ServerSocket, (struct sockaddr *)&clientAddr, &namelen);
				//接收到客户端连接
				if (pSocket->m_pTCPConnect->m_socket)
				{
					pSocket->m_pTCPConnect->m_RemoteHost = inet_ntoa(clientAddr.sin_addr);
					pSocket->m_pTCPConnect->m_RemotePort = ntohs(clientAddr.sin_port);
					
					//触发与客户端建立连接事件
					pSocket->OnAccept(pSocket->m_pOwnerWnd );
					//打开pClientSocket服务线程, 把本侦听类的指针传给客户端连接类
					pSocket->m_pTCPConnect->Open(pSocket);
					//添加到客户端连接队列中
					//m_ListClientSocket.AddTail(*pClientSocket);
				}
				else
				{
					//delete  pClientSocket;
				}
			}
		}
	}
	return 0;
}



/*--------------------------------------------------------------------
【函数介绍】:  打开TCP服务
【入口参数】:  (无)
【出口参数】:  (无)
【返回  值】:  <=0:打开TCP服务失败; =1:打开TCP服务成功
---------------------------------------------------------------------*/
int CTCPServer_CE::Open()
{
	WSADATA wsa;
	
	//1.初始化socket资源
	if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)
	{
		return -1;//代表失败
	}
	
	//2.创建套接字
	if ((m_ServerSocket=socket(AF_INET, SOCK_STREAM, 0))<0)
	{
		return -2;
	}
	
    SOCKADDR_IN  serverAddr;
	ZeroMemory((char *)&serverAddr,sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(m_LocalPort);
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	//3.绑定端口
	if (bind(m_ServerSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr))<0)
	{
		
		return -3 ;
	}
	//4.设置为侦听套接字,可同时响应8个客户的连接请求
	if (listen(m_ServerSocket,8)!=0)
	{
		return -3;
	}
	
	//4.设置监听套接字通讯模式为异步模式
	DWORD ul= 1;
	ioctlsocket(m_ServerSocket,FIONBIO,&ul);

	ResetEvent(m_exitThreadEvent);

	//5.创建侦听通讯线程,在线程里,等待客户端连接请求
	m_serverThreadHandle = CreateThread(NULL,0,SocketListenThread,this,0,NULL);
	if (m_serverThreadHandle == NULL)
	{
		closesocket(m_ServerSocket);
		return -1;
	}

	return 1;
}


/*--------------------------------------------------------------------
【函数介绍】:  关闭TCP服务
【入口参数】:  (无)
【出口参数】:  (无)
【返回  值】:  <=0:关闭TCP服务失败; =1:关闭TCP服务成功
---------------------------------------------------------------------*/
int CTCPServer_CE::Close()
{
	//结束通讯线程
	if( m_pTCPConnect->m_bSocketEnable )
		m_pTCPConnect->Close( );

	//产生结束侦听线程的事件
	SetEvent(m_exitThreadEvent);
	//等待1s,确保侦听线程已结束
	Sleep(1000);
	//关闭Socket,释放资源
	int err = closesocket(m_ServerSocket);
	if (err == SOCKET_ERROR)
	{
		return -1;
	}
	m_ServerSocket = NULL;

	//首先,关闭与所有客户端连接
	
	WSACleanup();
	return 1;
}  

/*-----------------------------------------------------------------
【函数介绍】: 向客户端发送数据
【入口参数】: buf:    待发送的数据
              len:    待发送的数据长度
【出口参数】: (无)
【返回  值】: > TRUE:发送数据成功;FALSE:发送数据失败
------------------------------------------------------------------*/
bool CTCPServer_CE::SendData(const char * buf , int len)
{
	int nBytesSent;
	int iErrorCode;

	if( !m_pTCPConnect->m_bSocketEnable )
		return FALSE;

	nBytesSent = m_pTCPConnect->SendData( buf, len );
	if (nBytesSent==SOCKET_ERROR )
	{
		//读取错误代码
		iErrorCode = WSAGetLastError();
		//触发socket的Error事件
		OnError(m_pOwnerWnd,iErrorCode);
		//触发与服务器端断开连接事件
		OnClose(m_pOwnerWnd);
		//关闭socket
		Close();
		return FALSE;
	}
	return TRUE;
}

⌨️ 快捷键说明

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