?? tcpserver_ce.cpp
字號:
// TCPServer_CE.cpp: implementation of the CTCPServer_CE class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TCPServer.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
//////////////////////////////////////////////////////////////////////
//構(gòu)造函數(shù)
CTCPServer_CE::CTCPServer_CE()
{
//創(chuàng)建線程退出事件句柄
m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
}
//析構(gòu)函數(shù)
CTCPServer_CE::~CTCPServer_CE()
{
//關(guān)閉線程退出事件句柄
CloseHandle(m_exitThreadEvent);
}
/*--------------------------------------------------------------------
【函數(shù)介紹】: 此線程用于檢測監(jiān)聽套接字事件。
【入口參數(shù)】: lparam:無類型指針,可以通過此參數(shù),向線程中傳入需要用到的資源。
在這里我們將CTCPServer_CE類實例指針傳進(jìn)來
【出口參數(shù)】: (無)
【返回 值】: 返回值沒有特別的意義,在此我們將返回值設(shè)為0。
---------------------------------------------------------------------*/
DWORD CTCPServer_CE::SocketThreadFunc(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)
{
//收到退出事件,結(jié)束線程
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)
{
//觸發(fā)錯誤事件
int iErrorCode = WSAGetLastError();
//觸發(fā)服務(wù)器socket的錯誤事件
pSocket->OnServerError(pSocket->m_pOwnerWnd,pSocket,iErrorCode);
//關(guān)閉服務(wù)器套接字
closesocket(pSocket->m_ServerSocket);
break;
}
if (ret > 0)
{
//判斷是否讀事件
if (FD_ISSET(pSocket->m_ServerSocket,&fdRead))
{
//如果調(diào)用了Listen,則表示觸發(fā)了OnAccept事件
SOCKADDR_IN clientAddr;
CTCPCustom_CE * pClientSocket = new CTCPCustom_CE();
int namelen = sizeof(clientAddr);
//等待,創(chuàng)建與客戶端連接的套接字
pClientSocket->m_socket = accept(pSocket->m_ServerSocket, (struct sockaddr *)&clientAddr, &namelen);
//接收到客戶端連接
if (pClientSocket->m_socket)
{
pClientSocket->m_RemoteHost = inet_ntoa(clientAddr.sin_addr);
pClientSocket->m_RemotePort = ntohs(clientAddr.sin_port);
//觸發(fā)與客戶端建立連接事件
pSocket->OnClientConnect(pSocket->m_pOwnerWnd,pClientSocket);
//打開pClientSocket服務(wù)線程
pClientSocket->Open(pSocket);
//添加到客戶端連接隊列中
m_ListClientSocket.AddTail(*pClientSocket);
}
else
{
delete pClientSocket;
}
}
}
}
return 0;
}
/*--------------------------------------------------------------------
【函數(shù)介紹】: 打開TCP服務(wù)
【入口參數(shù)】: (無)
【出口參數(shù)】: (無)
【返回 值】: <=0:打開TCP服務(wù)失敗; =1:打開TCP服務(wù)成功
---------------------------------------------------------------------*/
int CTCPServer_CE::Open()
{
WSADATA wsa;
//1.初始化socket資源
if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)
{
return -1;//代表失敗
}
//2.創(chuàng)建監(jiān)聽套接字
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.綁定監(jiān)聽套接字
if (bind(m_ServerSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr))<0)
{
return -3 ;
}
//4.監(jiān)聽套接字開始監(jiān)聽
if (listen(m_ServerSocket,8)!=0)
{
return -3;
}
//4.設(shè)置監(jiān)聽套接字通訊模式為異步模式
DWORD ul= 1;
ioctlsocket(m_ServerSocket,FIONBIO,&ul);
ResetEvent(m_exitThreadEvent);
//5.創(chuàng)建通訊線程,在線程里,等待客戶端接入
m_serverThreadHandle = CreateThread(NULL,0,SocketThreadFunc,this,0,NULL);
if (m_serverThreadHandle == NULL)
{
closesocket(m_ServerSocket);
return -1;
}
return 1;
}
/*--------------------------------------------------------------------
【函數(shù)介紹】: 關(guān)閉TCP服務(wù)
【入口參數(shù)】: (無)
【出口參數(shù)】: (無)
【返回 值】: <=0:關(guān)閉TCP服務(wù)失敗; =1:關(guān)閉TCP服務(wù)成功
---------------------------------------------------------------------*/
int CTCPServer_CE::Close()
{
//結(jié)束通訊線程
SetEvent(m_exitThreadEvent);
Sleep(1000);
//關(guān)閉Socket,釋放資源
int err = closesocket(m_ServerSocket);
if (err == SOCKET_ERROR)
{
return -1;
}
m_ServerSocket = NULL;
//首先,關(guān)閉與所有客戶端連接
POSITION pos = m_ListClientSocket.GetHeadPosition();
while (pos != NULL)
{
CTCPCustom_CE &tmpTcpCustom = m_ListClientSocket.GetAt(pos);
if (!tmpTcpCustom.Close())
{
AfxMessageBox(L"關(guān)閉客戶端socket錯誤");
}
m_ListClientSocket.RemoveHead();
pos = m_ListClientSocket.GetHeadPosition();
}
WSACleanup();
return 1;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -