IO完成

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
int IniVariables()
{
int result=0;
TCHAR buf[512]={0};
::GetModuleFileName( NULL,buf, 512 );
selfPath=buf;
int pos=(int)selfPath.find_last_of('\\');
selfPath=selfPath.substr(0,pos);
//创建完成端口
if (g_hIOCP== NULL)
{
std::string msg="创建完成端口g_hIOCP失败";
PushLog(msg);
return 3;
//创建完成端口失败
}
//cup个数
SYSTEM_INFO sysinfo;
::GetSystemInfo(&sysinfo);
CpuCount=(int)sysinfo.dwNumberOfProcessors;
void Lock(LPCRITICAL_SECTION crit_sec)
{
::EnterCriticalSection(crit_sec);
}
void UnLock(LPCRITICAL_SECTION crit_sec)
{
::LeaveCriticalSection(crit_sec);
}
//初始化变量
std::deque<std::string> runLog; //系统运行日志队列
std::string selfPath=""; //文件所在路径
///////////////////////////////////////////////////////////////////////////////////////////////
pSession->LoginName="";
pSession->fIsLogin=false;
shutdown(pSession->sock,SD_BOTH);
closesocket(pSession->sock);
pSession->sock=INVALID_SOCKET;
}
smsClient.SetEmptyElement(pSession->nUserIndex);
}
}
void CloseSession(int nIndex)
{
if(smsClient.GetData(nIndex))
{
//告诉客户端服务器要关闭
if(smsClient.GetData(nIndex)->sock!=INVALID_SOCKET)
{
ReplyClient(smsClient.GetData(nIndex),0,0,"");
//关闭清除
WSACleanup();
PushLog("启动服务失败");
return -1;
}
::InitializeCriticalSection(&Csec_Client);
::InitializeCriticalSection(&Csec_log);
CIniFile theFile(selfPath+"\\Config.ini");
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[1024*400];
INT nOvFlag;
} _TCOMPLETIONPORT, * _LPTCOMPLETIONPORT;
//登录到服务器的客户信息
class CClientInfo
{
public:
bool fIsLogin; //是否登录
int nUserIndex; //客户数据在链表的位置
time_t tConnectTime; //连接到服务器的时间
int sendSpeed; //发送短信的每秒最大速率,默认1条每秒
int LinkCheck; //发送连接检查数据未响应次数,如果超过3次未响应则断开连接
}
smsClient.SetEmptyElement(nIndex);
}
}
void CloseSession(CClientInfo* pSession)
{
if(pSession)
{
if(pSession->sock!=INVALID_SOCKET)
{
ReplyClient(pSession,0,0,"");
//重叠IO
OVERLAPPED Overlapped; //关联的重叠IO变量
WSABUF DataBuf; //IO的数据缓冲区
_OP_FLAG nOvFlag; //完成状态标志(op_recv,op_send,op_accept)
SOCKET sock; //客户端套接字
unsigned long total_length; //数据包的总长度
CThreadManage ThreadManage; //线程管理
bool IsIniVars=false; //全局资源是否被初始化过
//////////////////////////////////////////////////////////////////////////////////////////////
smsClient.GetData(nIndex)->LoginName="";
shutdown(smsClient.GetData(nIndex)->sock,SD_BOTH);
closesocket(smsClient.GetData(nIndex)->sock);
smsClient.GetData(nIndex)->sock=INVALID_SOCKET;
std::string logPath=selfPath+"\\run_log";
//判断文件夹是否存在
if(!PathFileExists(logPath.c_str()))
{
//创建文件夹
::CreateDirectory(logPath.c_str(),NULL);
}
LogFileName=".\\run_log\\Service";
CRITICAL_SECTION Csec_Client; //数据链表操作锁
//当前的客户连接
CWHDynamicArray<CClientInfo> smsClient;
std::string ServerPort=&AL_SECTION Csec_log;
}
}
void CloseClientSession()
#include <process.h>
#include "ServiceThread.h"
extern std::string LogFileName; //日志文件名
//做日志记录
extern void _stdcall PushLog(std::string LogMsg);
//判断连接IP是否有效
服务头文件:
#pragma once
#include <vector>
using namespace std;
//IO操作类型标志
enum _OP_FLAG
{
OP_NONE,
OP_ACCEPT,
OP_RECV,
OP_SEND
};
//完成键结构
typedef struct tag_TCOMPLETIONPORT
extern int _stdcall DealRecvDataPacket(CClientInfo* pClient,CADOConnection& m_ADO);
//删除记录
extern void DeleteRecord(std::string OnlySign,std::string TableName,std::string KeyName,CADOConnection& m_ADO);
//读取监听端口
ServerPort=theFile.GetParamValue("smsQueue","ServerPort");
//ManagePort=theFile.GetParamValue("smsQueue","ManagePort");
//读取超时设置
std::string strSuperTime=theFile.GetParamValue("smsQueue","SuperTime");
extern int _stdcall IsValidIP(CADOConnection& m_ADO,std::string IP);
//删除登录的客户端的记录
extern void DelLoginUser(CADOConnection& m_ADO,std::string UserID);
//将接收的数据包交给分析线程处理
char *stopstring;
SuperTime=strtod(strSuperTime.c_str(),&stopstring);
SuperTime=SuperTime*60*1000;
g_hIOCP = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0);
windows完成端口服务器的另一种实现
几年前为了在windows下实现一个高效简洁的服务器,不得不使用wondows下的完成端口socket编程.
参考了很多的完成端口的代码,始终不是很满意,因此,自己根据相关的原理实现一个.现在公布如下,供需要学习完成端口的同仁们参考.
整个服务由监听线程,工作线程构成.监听线程负责监听连接的到来,工作线程负责通知当有接受数据的到来.
if(!IsIniVars)
{
////初始化winsock运行环境
WSADATA WSAData = { 0 };
WORD WSA_VERSION=MAKEWORD(2,0);
if ( 0 != WSAStartup(WSA_VERSION, &WSAData ))
{
PushLog("初始化socket环境失败");
result=1;
IsIniVars=true;
}
else
{
result=1;
}
return result;
}
//
//通知完成端口退出
void NoticeCompletionExit()
{
//退出端口等待
if(g_hIOCP)
{
::PostQueuedCompletionStatus(g_hIOCP,0,NULL,NULL);
//数据重发
extern void ReplyClient(CClientInfo* pClient,int replyType,unsigned int lresult/*只对登录回复有用*/,std::string MsgAnswerID);
////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
CClientInfo(void)
{
sock=INVALID_SOCKET;
total_length=0;
pack_len=0;
}
~CClientInfo(void)
{
}
}
};
服务实现文件:
/****************************************************************************
HANDLE g_hIOCP=NULL; //完成端口句柄
int WaitTime=180; //最大等待客户发送登录数据时间,默认1分钟,超过时间没有收到登陆数据断开连接
int CpuCount=2; //服务务器cpu个数
double SuperTime=180000; //最大超时登录时间默认3分钟
///完成端口服务器
///编写人:秦柏林
///
///最后修改日期:2003-06-27
****************************************************************************/
#pragma once
#include <shlwapi.h>
unsigned long pack_len; //当前读取的长度
char RecvBuffer[1024*4]; //接收数据缓冲区
char DealBuffer[1024*4]; //一个通讯包的数据
char Buffer[1024*4]; //发送接收数据缓冲池
int nSendBufferLen; //发送数据大小
相关文档
最新文档