windows下封装一个soket服务器类(事件模型)

  • Post author:
  • Post category:其他


———————————MySocketServer.h————————————————-

#ifndef __MYSOCKETSERVER_H__

#define __MYSOCKETSERVER_H__

#include <WINSOCK2.H>

typedef void (*TMsgProFun)(char *pMsg,int &ilen);

class CSockeServer

{


public:



static CSockeServer *GetInstance(TMsgProFun MsgPro = NULL);



~CSockeServer();



char * StartServer(u_short port = 5150,const char *strIp = NULL); //开启服务,失败返回相应的错误log。正确返回NULL(如果开启了服务则一般不会返回)。



static void RegisterMsgFun(TMsgProFun MsgPro);//用来注册消息处理函数,对接收到的消息进行相应的处理。



static void Close();

private:



CSockeServer(){};



static DWORD __stdcall WorkerThread(LPVOID lpParam);



static DWORD __stdcall AcceptThread(LPVOID lpParam); //accept线程,监听链接请求



static void  Cleanup(int index);

private:



static int


ms_iTotalConn;



static SOCKET


ms_CliSocketArr[MAXIMUM_WAIT_OBJECTS];



static WSAEVENT


ms_CliEventArr[MAXIMUM_WAIT_OBJECTS];



const static int


Msg_Size;



static TMsgProFun   pMsgProcFun;



static char         LogBuf[1024]; //打印log



static SOCKET       ms_sListen;



static HANDLE       ms_HandThread[2];



static CSockeServer *ms_pSingleServer;



static HANDLE       ms_hSemaphore;



static bool         ms_bEndThread;

};

#endif

———————————MySocketServer.cpp————————————————-

#include “MySocketServer.h”

#include <stdio.h>

#pragma comment(lib,”ws2_32.lib”)

#define LISTENNUM 10 //最大监听数

int          CSockeServer::ms_iTotalConn     = 0;

SOCKET       CSockeServer::ms_CliSocketArr[MAXIMUM_WAIT_OBJECTS];

WSAEVENT     CSockeServer::ms_CliEventArr[MAXIMUM_WAIT_OBJECTS];

const int    CSockeServer::Msg_Size          = 2048;

TMsgProFun   CSockeServer::pMsgProcFun


= NULL;

SOCKET       CSockeServer::ms_sListen        = 0;

CSockeServer *CSockeServer::ms_pSingleServer = NULL;

HANDLE


CSockeServer::ms_HandThread[2];

char         CSockeServer::LogBuf[1024];

HANDLE       CSockeServer::ms_hSemaphore     = NULL;

bool         CSockeServer::ms_bEndThread     = false;

CSockeServer *CSockeServer::GetInstance(TMsgProFun MsgPro)

{




if (NULL == ms_pSingleServer)



ms_pSingleServer = new CSockeServer();



ms_hSemaphore = CreateSemaphore(NULL,1,1,NULL);



RegisterMsgFun(MsgPro);



return ms_pSingleServer;

}

void CSockeServer::RegisterMsgFun(TMsgProFun MsgPro)

{




WaitForSingleObject(ms_hSemaphore,INFINITE);



pMsgProcFun = MsgPro;



ReleaseSemaphore(ms_hSemaphore,1,NULL);

}

CSockeServer::~CSockeServer()

{



if (0 != ms_iTotalConn)



{




Close();



}



//关闭信号量句柄



if (NULL != ms_hSemaphore)



{




CloseHandle(ms_hSemaphore);



ms_hSemaphore = NULL;



}



if (NULL != ms_pSingleServer)



{




delete ms_pSingleServer;



ms_pSingleServer = NULL;



}

}

char * CSockeServer::StartServer(u_short port,const char *strIp)

{




WSADATA     wsaData;



SOCKADDR_IN local;



DWORD       dwThreadId;



int         iaddrSize = sizeof(SOCKADDR_IN);



ms_bEndThread = false;



// Initialize Windows Socket library



WSAStartup(0x0202, &wsaData);



// Create listening socket



ms_sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);



if (SOCKET_ERROR == ms_sListen)



{




sprintf_s(LogBuf,1024,”Create socket fail! Errode:%d”,GetLastError());



return LogBuf;



}






// Bind



if (NULL == strIp)



local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);



else



local.sin_addr.S_un.S_addr = inet_addr(strIp);



local.sin_family


= AF_INET;



local.sin_port


= htons(port);



if (SOCKET_ERROR == bind(ms_sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)))



{




sprintf_s(LogBuf,1024,”bind fail! Errode:%d”,GetLastError());



return LogBuf;



}



// Listen



if (SOCKET_ERROR == listen(ms_sListen, LISTENNUM))



{




sprintf_s(LogBuf,1024,”listen fail! Errode:%d”,GetLastError());



return LogBuf;



}






if (NULL == pMsgProcFun)



{




sprintf_s(LogBuf,1024,”%s”,”No registration function,please register it,and try agin.”);



return LogBuf;



}



// Create worker thread



ms_HandThread[0] = CreateThread(NULL,0,WorkerThread,NULL,0,&dwThreadId);



ms_HandThread[1] = CreateThread(NULL,0,AcceptThread,NULL,0,&dwThreadId);



return NULL;

}

DWORD CSockeServer::AcceptThread(LPVOID lpParam)

{




SOCKET      sClient;



int         iaddrSize = sizeof(SOCKADDR_IN);



SOCKADDR_IN client;



while (TRUE)



{



// Accept a connection



sClient = accept(ms_sListen, (struct sockaddr *)&client, &iaddrSize);



if (ms_bEndThread)



return 0;



//sprintf(buf,”Accepted client:%s:%d\n”, inet_ntoa(client.sin_addr), ntohs(client.sin_port));



// Associate socket with network event



ms_CliSocketArr[ms_iTotalConn] = sClient;



ms_CliEventArr[ms_iTotalConn]  = WSACreateEvent();



WSAEventSelect(ms_CliSocketArr[ms_iTotalConn],ms_CliEventArr[ms_iTotalConn],FD_READ | FD_CLOSE);



ms_iTotalConn++;



}



return 0;

}

DWORD CSockeServer::WorkerThread(LPVOID lpParam)

{




int              ret, index;



WSANETWORKEVENTS NetworkEvents;



char             szMessage[Msg_Size];



while (TRUE)



{



ret = WSAWaitForMultipleEvents(ms_iTotalConn, ms_CliEventArr, FALSE, 1000, FALSE);



if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)



{



continue;



}



if (ms_bEndThread) //结束线程



return 0;



index = ret – WSA_WAIT_EVENT_0;



WSAEnumNetworkEvents(ms_CliSocketArr[index], ms_CliEventArr[index], &NetworkEvents);



if (NetworkEvents.lNetworkEvents & FD_READ)



{



// Receive message from client



ret = recv(ms_CliSocketArr[index], szMessage, Msg_Size, 0);



if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))



{



Cleanup(index);



}



else



{



szMessage[ret] = ‘\0’;





WaitForSingleObject(ms_hSemaphore,INFINITE); //线程同步保护



pMsgProcFun(szMessage,ret);



ReleaseSemaphore(ms_hSemaphore,1,NULL);





send(ms_CliSocketArr[index], szMessage, strlen(szMessage), 0);





}



}



if (NetworkEvents.lNetworkEvents & FD_CLOSE)



{



Cleanup(index);



}



}



return 0;

}

void  CSockeServer::Cleanup(int index)

{




closesocket(ms_CliSocketArr[index]);



WSACloseEvent(ms_CliEventArr[index]);



if (index < ms_iTotalConn – 1)



{



ms_CliSocketArr[index] = ms_CliSocketArr[ms_iTotalConn – 1];



ms_CliEventArr[index] = ms_CliEventArr[ms_iTotalConn – 1];



}



ms_iTotalConn–;

}

void CSockeServer::Close()

{




//关闭socket服务



for (int index = ms_iTotalConn-1;index >= 0;index–)



{




Cleanup(index);



}



//关闭线程



if (NULL != ms_HandThread[0] || NULL != ms_HandThread[1])



{




CloseHandle(ms_HandThread[0]);



CloseHandle(ms_HandThread[1]);



ms_bEndThread = true;



Sleep(3000);



ms_HandThread[0] = ms_HandThread[1] = NULL;



}



WSACleanup();

}

参考文献:http://bk6.blog.163.com/blog/static/24498560201021635453185/



版权声明:本文为xs813原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。