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