// IocpModeSvr.h: interface for the CIocpModeSvr class.
//
//
#if !defined(AFX_IOCPMODESVR_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)
#define AFX_IOCPMODESVR_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
#include <list>
#include <afxtempl.h>
#include <winsock2.h>
#include <fstream>
#include <time.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define MAX_BUFFER_SIZE 32768*2+64
/***************************************************************************************
文件名:IocpModeSvr.h
类名:CIocpModeSvr
类说明:本类是一个完成端口模型的网络服务器引擎
运行平台:WinNT3.5以上版本、Windows2000
输入接口说明:
本类接收一个回调函数地址,该函数具有如下原型
void _stdcall ProcessRecvData(unsigned long sIP,
SOCKET sClient,
char * pData,
unsigned long DataLength);
此回调函数用来接收从客户端发来的数据或者某客户端断开连接的通知(有始有终)。
sIP : 表示数据通知的客户端IP地址
sClient : 服务器用于和客户端通迅的套接字,
如果不是断开连接消息,则您可使用此参数调用SendMsg向客户端发送数据
Data : 本次操作的数据
DataLength :本次操作数据的数据长度
提示:如果pData==NULL 并且DataLength 则表示那是客户端断开连接的消息,请针对业务做处理吧。
输出接口说明:
引擎初始化函数,第一参为回调地址(必须正确填写),第二参为服务端口号
初始化成功返回真,否则返回假
bool Init(ProcessRecvData* pProcessRecvData,unsigned long iSvrPort=SVRPORT);
引擎反初始化函数,请在程序退出时调用,或者在程序需要重新启动服务时调用
void UnInit();
以下在关于发送消息函数组的接口说明
1、向目标IP客户端发送数据,
第一参为目标客户端IP,
第二参为数据区地址,
第三参为数据区长度
成功"提交"返回真,否则返回假,
那可能是因为客户端已经断开或者根本就没有连接。
bool SendMsg(LPCTSTR TargetIp,char * pData,unsigned long Length);
2、向目标套接字发送数据
第一参为客户端套接字
第二参为数据区地址
第三参为数据区长度
成功"提交"返回真,否则返回假
那可能是因为客户端已经断开连接
提示:此函数为不需要检索的发送数据函数,具有高效率的特性。
你可以在你的数据通知回调中以第二参的sClient直接填写于
第一参中发送数据,如果你在接收到数据时需要回传消息,请
使用此函数
成功"提交"返回真,否则返回假
bool SendMsg(SOCKET sClient,char * pData,unsigned long Length);
3、向所有连线客户端发送数据
发送数据到所有已经正确连线的客户端
第一参为数据区地址
第二参为数据区长度
成功"提交"返回真,否则返回假
大部分情况下都会返回真 ^_^
bool SendMsgToAll(char * pData,unsigned long Length);
4、向除了某个IP外的其它所有在线客户端发送数据
第一参为除外的IP
第二参为数据区地址,
第三参为数据区长度,
成功"提交"返回真,否则返回假
大部分情况下都会返回真
bool SendMsgToOther(LPCTSTR SourceIp,char* pData,unsigned long Length);
5、向除了某个Socket久的其它所有在线客户端发送数据
第一参为除外的Socket
第二参为数据区地址
第三参为数据区长度
成功"提交"返回真,否则返回假
大部分情况下都会返回真
bool SendMsgToOther(SOCKET ExceptSocket,char * pData,unsigned long Length);
附助函数组1
1、const char * GetLocalIpAdd()
返回本地Ip地址,返回值为点分十进制的字符串
2、unsigned short GetSvrPort()
返回服务使用的侦听端口号
附助函数助2
1、bool DisConnectClient(LPCTSTR ClientIp);
切断参数中指定的IP的客户端的连接,成功返回真,否则返回假。
2、bool DisConnectClient(SOCKET sClient);
切断参数中指定的客户机的连接,参数中指定了要切断了套接口。
3、void DisConnectAll();
切断所有客户机的连接。
***************************************************************************************/
#define SVRPORT 10012 //服务端口
#define RECV_POSTED 0 //接收数据
#define SEND_POSTED 1 //发送数据
//单句柄数据
typedef struct _PER_HANDLE_DATA
{
unsigned long IpAddr; //IP地址
SOCKET sClient; //套接字
unsigned long Port;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
/**
1、WSABUF结构的原型:
typedef struct __WSABUF {
u_long len;
char FAR* buf;
} WSABUF, *LPWSABUF;
2、 OVERLAPPED原型:OVERLAPPED结构包含了用于异步(或重叠) 输入输出(I/O)的信息。
typedef struct _OVERLAPPED {
ULONG_PTR Internal; //保留,OS使用
ULONG_PTR InternalHigh; //保留,OS使用
union{
struct{
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer; //保留,OS使用
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
*/
//IO操作数据
typedef struct _PER_IO_OPERATION_DATA
{
OVERLAPPED OverLapped; //重叠结构
WSABUF RecvDataBuf; //接收数据缓冲区(长度、指针)
WSABUF SendDataBuf; //发送数据缓冲区(长度、指针)
char RecvBuf[MAX_BUFFER_SIZE]; //接收缓冲区
char SendBuf[MAX_BUFFER_SIZE]; //发送缓冲区
bool OperType; //IO操作类型表示
}PER_IO_OPERATION_DATA, *PPER_IO_OPERATION_DATA;
//回调处理数据函数原型 direction=0 是服务器向外发出数据 =1 是服务器收到数据
typedef void ProcessRecvData(unsigned long sIP,SOCKET sClient,unsigned short port,int direction,char * pData,unsigned long DataLength,DWORD userdata);
DWORD WINAPI ServerWorkerProc(LPVOID lParam);
DWORD WINAPI ListenProc(LPVOID lParam);
class CIocpModeSvr
{
public:
int m_bClosing;
//构造函数和析构函数
CIocpModeSvr();
virtual ~CIocpModeSvr();
public:
//引擎初始化
bool Init(ProcessRecvData* pProcessRecvData,char *serverip,unsigned long iSvrPort=SVRPORT,DWORD userdata=NULL);
bool StartServer(ProcessRecvData *pProcessRecvData,DWORD userdata=NULL);
//引擎反初始化
void UnInit();
public:
//用于发送消息的函数组
bool SendMsg(LPCTSTR TargetIp,char * pData,unsigned long Length,bool bshowsend);
bool SendMsg(SOCKET sClient, char * pData,unsigned long Length,bool bshowsend);
bool SendMsgToAll(char * pData,unsigned long Length,bool bshowsend);
bool SendMsgToAll(char *pData,unsigned long Length,unsigned int us,byte times,byte delta,bool bshowsend);
bool SendMsgToOther(LPCTSTR ExceptIp, char * pData,unsigned long Length,bool bshowsend);
bool SendMsgToOther(SOCKET ExceptSocket,char * pData,unsigned long Length,bool bshowsend);
public:
//获得本地Ip地址
const char * GetLocalIpAdd()
{
if(IsStart) return HostIpAddr.c_str();
else return NULL;
}
//获得服务器使用的端口号
unsigned short GetSvrPort()
{
if(IsStart) return m_SvrPort;
else return 0;
}
void GetIpAndPort(char *ip,unsigned short &port)
{
if(IsStart)
{
memcpy(ip,HostIpAddr.c_str(),16);
port=m_SvrPort;
}
else
{
ip=NULL;
port=0;
}
}
HANDLE m_hOneOkEvent; //一台设备成功
HANDLE m_hAllOkEvent; //全部设备成功
//用于断开连接的函数组
public:
bool DisConnectClient(LPCTSTR ClientIp);
bool DisConnectClient(SOCKET sClient);
void DisConnectAll();
void GetClientList(unsigned long *IPlist,int &count);
CRITICAL_SECTION cInfoSection; //客户信息临界保护量
unsigned short m_SvrPort; //服务端口记录
protected:
int InitNetWork(char *serverip,unsigned int SvrPort=SVRPORT, std::string *pHostIpAddress=NULL);
void WriteLogString(LPCTSTR strLog);
ProcessRecvData* m_pProcessRecvData;
private:
HANDLE CompletionPort; //完成句柄
std::string HostIpAddr; //主机IP
CArray <PER_HANDLE_DATA,PER_HANDLE_DATA> ClientInfo; //客户信息列表
bool IsStart; //服务是否已经启动
SOCKET ListenSocket; //侦听端口
HANDLE ListenThreadHandle; //侦听线程句柄,用于反初始化时销毁侦听线程
DWORD m_dwUserData; //用户数据
friend DWORD WINAPI ServerWorkerProc(LPVOID lParam);
friend DWORD WINAPI ListenProc(LPVOID lParam);
//ofstream fout;
};
#endif // !defined(AFX_IOCPMODESVR_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)