📄 sock.cpp
字号:
/*************************************************
网络类的定义
本网络类利用完成端口模型,对网络相关功能进行了封装
为上层提供透明的网络传输
作者:颜永华
**************************************************/
#include "StdAfx.h"
#include ".\sock.h"
#define MIN_PACKET 8
typedef CTypedPtrList<CPtrList, CConnectInfo*> CMyList;
CMyList ConnectList;
BOOL EndFlag=FALSE;
//(1)fdsjfdskjfds
CSock::CSock(void)
{
}
CSock::~CSock(void)
{
}
/*
(2)mmm->CreateIOCPWorkerThread(ddd);
创建完成端口工作线程
判断什么时候
启动ServerWorkerThread
参数nThread为创建线程的个数
*/
INT CSock::CreateIOCPWorkerThread(int nThread)
{
DWORD dwThreadID;
if(g_hIOCP != INVALID_HANDLE_VALUE)
{
SYSTEM_INFO SystemInfo;
//1)创建完全端口
if ((g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
return -1;
GetSystemInfo(&SystemInfo);
//根据处理机的个数创建线程/一般一个处理机创建一个工作线程
for (UINT i = 0; i < SystemInfo.dwNumberOfProcessors * nThread; i++)
{
HANDLE ThreadHandle;
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, g_hIOCP, 0, &dwThreadID)) == NULL)
return -1;
CloseHandle(ThreadHandle);
}
return SystemInfo.dwNumberOfProcessors * nThread;
//系统处理器的个数*线程数
}
return -1;
}
/*
完成端口上的工作线程
本线程处理接收和发送数据
以及对数据库的访问,为业务层提供透明的数据
本线程函数的好坏,直接影响本网络模型的运行效率
*/
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
DWORD dwBytesTransferred;
printf("server Thread\n");
CConnectInfo* pConnInfo;
LPOVERLAPPEDEX pOverlapped;
while (TRUE)
{
if(EndFlag==TRUE)//如果结束标志为真 则结束线程
return 0;
GetQueuedCompletionStatus((HANDLE)CompletionPortID,
&dwBytesTransferred,(PULONG_PTR)&pConnInfo,
(LPOVERLAPPED*)&pOverlapped,WSA_INFINITE);
if(dwBytesTransferred==0)
{ //套接字错误
::GlobalFree(pOverlapped->DataBuf.buf);
::GlobalFree(pOverlapped);
//关闭套接字
closesocket(pConnInfo->sock);
continue;
}else if(pOverlapped->nOvFlag==RECV)
{ //接受操作完成 处理接受到的封包
pConnInfo->handleRecvPacket(pOverlapped,dwBytesTransferred);
}else if(pOverlapped->nOvFlag==SEND)
{ //发送数据完成 清空发送缓冲区
::GlobalFree(pOverlapped->DataBuf.buf);
::GlobalFree(pOverlapped);
continue;
}
}
return 0;
}
/*
创建监听套接字 并植入监听状态
*/
int CSock::InitServerSocket()
{
sListen=WSASocketA(AF_INET, SOCK_STREAM, 0,NULL, 0, WSA_FLAG_OVERLAPPED);
sockaddr_in localaddr;
localaddr.sin_family=AF_INET;
localaddr.sin_addr.S_un.S_addr=::inet_addr("192.168.0.136");
localaddr.sin_port=::htons(8888);
if(SOCKET_ERROR==(bind(sListen,(sockaddr*)&localaddr,sizeof(localaddr))))
{
::MessageBox(NULL,"bind is err","err",0);
return 0;
}
if(SOCKET_ERROR==(listen(sListen,5)))
{
::MessageBox(NULL,"listen is err","err",0);
return 0;
}
//创建接受连接线程
DWORD id;
HANDLE hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)AcceptThread,(LPVOID)this,0,&id);
CloseHandle(hThread);
//创建工作者线程
CreateIOCPWorkerThread((int)1);
return 1;
}
/*
接受连接线程
参数lpParameter被传递为网络套接字对象
以方便对对象数据的访问,将接受连接和创建套接字分开到
不同的线程中,主要是为了不应为在做其他工作而影响到连接进入
*/
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
//参数转换
CSock *pSock=(CSock*)lpParameter;
SOCKET SClient;
sockaddr_in addr;
int len=sizeof(sockaddr);
while(1)
{
if(EndFlag==TRUE)
{
return 0;
}
SClient=::WSAAccept(pSock->sListen,(sockaddr*)&addr,&len,NULL,0);
if(SClient!=INVALID_SOCKET)
{
SendMessage(pSock->hWnd,WM_SOCKET,(WPARAM)0X0101,(LPARAM)&addr);
CConnectInfo *pConnInfo=new CConnectInfo;
if(pConnInfo)
{
pConnInfo->sock=SClient;
pConnInfo->netaddr=addr;
//添加对象到连接列表
//ConnectList.InsertAfter(ConnectList.GetHeadPosition(),pConnInfo);
//ConnectList.AddTail(pConnInfo);
printf("%s\n",inet_ntoa(pConnInfo->netaddr.sin_addr));
//关联到完成端口
CreateIoCompletionPort((HANDLE)pConnInfo->sock,pSock->g_hIOCP,(ULONG_PTR)pConnInfo,0);
//发送密钥
pConnInfo->sendKey(pConnInfo->Key.SendKey);
pConnInfo->sendKey(pConnInfo->Key.RecvKey);
}
}
//return 0;
}
return 0;
}
/*
关闭某个套接字
关闭连接,为了管理客户端
*/
void CSock::CloseConnect(CConnectInfo *pConnInfo)
{
closesocket(pConnInfo->sock);
//ConnectList.RemoveAt(ConnectList.Find(pConnInfo));
delete pConnInfo;
}
/*
结束服务
*/
void CSock::EndServerSocket()
{
EndFlag=TRUE;
//Sleep(10);
//CloseAllConnect();
CloseHandle(g_hIOCP);
closesocket(sListen);
sListen=INVALID_SOCKET;
//Sleep(10);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -