---------------------------------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 WSAEVENTms_CliEventArr[MAXIMUM_WAIT_OBJECTS];
const static intMsg_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/