IOCP_API之TCP服务器编程

shenyi0106 2011-01-27 04:10:56
本文基于沈毅(shenyi0106@163.com qq:52851771)所提供的IOCP_API组件来搭建TCP服务器。
下载地址:http://download.csdn.net/source/2960211

本文适用于对winsock有一定了解的开发者,当然,如果你不了解winsock也没有关系,IOCP_API为您提供了高度封装的API,您只需要定义几个回调函数,调用几个API即可完成服务器搭建工作,使您可以专注于业务逻辑处理,而无需了解了解通讯底层。

如果您需要解压缩支持,可以加上Compress.h头文件;如果需要提供大数据包支持,可以加上Packet.h头文件。


下面将介绍如何使用IOCP_API组件:
首先,导入IOCPServer.h头文件。如果你的工程中不包括socket支持,那查看IOCPServer.h头文件,将部分注释打开。
其次,定义回调函数。共有三个回调函数,分别是数据处理回调,连接处理回调和连接关闭回调,定义格式如下:

  //数据处理回调
void DataProcCallBack(SOCKET socket, char * recvBuf, int len);
//连接处理回调
BOOL OnConn(SOCKET socket, char * ip, int port);
//连接关闭回调
void OnClientClose(SOCKET socket, char * ip, int port);

如果是定义类成员函数,请将函数定义成静态成员函数,原因省略万字......

再次,调用IOCP_API的函数初始化并启动服务器:
HANDLE m_hIocp = IOCPInitServer(DataProcCallBack,OnConn,OnClientClose,4,5000,10);
其中各个参数的意义,请参考IOCPServer.h头文件中的说明。

//设置服务器参数(可选)
IOCPSetMaxAccept(20000); //设置最大可以接受的客户端数量
IOCPSetTickTime(300); //设置服务器心跳检测的间隔时间,单位是秒

最后,如果你在初始化时已经设置了线程池模式,那么你只需要在你的DataProcCallBack函数里专心处理你自己的业务逻辑即可。当然这里不用线程池模式也可以,完全取决于你自己的业务需求。

如果需要回发数据,通过IOCPSend函数发送。

在此组件中还提供很多其他的辅助功能,比如:
调用IOCPCloseClient可以强制关闭某个连接,IOCPGetClientCount可以获得当前客户端数,IOCPGetSocketName获得本地IP信息,IOCPGetPeerName获得远端IP信息,
IOCPSetUserData可以设置句柄相关的任何数据,IOCPGetUserData获得句柄相关的任何数据。

性能怎么说呢,由于没有测试环境,只做过三四台机器5K多的echo(500ms间隔)并发测试,服务器是普通的双核PC,100M网络,只能说资源占用率比较低,CPU控制在10%以下,内存占用也很低。

程序的不足:
1. 采用Accept + 线程模式来接受客户端连接,在大规模并发连接时会丢失一些客户端连接。
2. 由于采用了内存池管理内存,所以长时间运行不会出现过多的内存碎片,但是由于所采用的内存池是只增加不减少的,也就导致长时间大规模处理数据时,会导致内存上涨,但是业务量下降时,内存占用量并不会减小。
3.虽然写这个库已经有一段时间了,但是由于对IOCP的理解可能还不是那么好,组件难免回有问题,也请大家多多指教。
...全文
23423 194 打赏 收藏 转发到动态 举报
写回复
用AI写文章
194 条回复
切换为时间正序
请发表友善的回复…
发表回复
zdleek 2013-10-10
  • 打赏
  • 举报
回复
好东西,支持楼主分享~
苦逼De程序员 2013-07-09
  • 打赏
  • 举报
回复
楼主教下我把 扣扣419752573
oushengfen 2013-07-01
  • 打赏
  • 举报
回复
WINSOCK我也想学习一下。
sh98_wgf 2013-05-13
  • 打赏
  • 举报
回复
更简单的,像楼上同学建议的,加个参数,我自己保存this指针。
sh98_wgf 2013-05-13
  • 打赏
  • 举报
回复
没看你的代码,只看你那三个回调函数,就发现过问题,你要求必须使用静态成员函数,静态成员函数是没有this指针的,在实际使用中有很多不便。其实用成员函数也是可以的,将成员函数地址和this指针传过去,你调用的时候加this调用,这就方便多了。我在我自己封的Telnet协议类中,就用的这招,比如用户传个CRichEdit的扩展类的成员函数进去,就能实时在EDIT里输出Telnet收到的数据,完全没有静态成员函数的限制,超爽。获取成员函数指针我是Copy别人的代码,如下: //获取成员函数地址 #define GetMemberFuncAddr(FuncAddr,FuncType)\ { \ __asm \ { \ mov eax,offset FuncType \ }; \ __asm \ { \ mov FuncAddr, eax \ }; \ } 调用方法如下: DWORD f1; GetMemberFuncAddr( f1, COutputView::OutputString ); f1就得到成员函数的地址了,然后将this指针一起传你,你调用的时候加个this就搞定了。 有分就给点吧
fly4free 2013-04-17
  • 打赏
  • 举报
回复
虽然过了好久,可是回调函数,能不能增加一个参数 PVOID param , IOCPInitServer 也增加一个 PVOID param ? 后者传递的 param 在 需要的时候直接传递给 各个回调函数? 擦,打了半天包括修改因键盘导致的失误,后来想到,貌似有源码啊
wumn29 2013-04-04
  • 打赏
  • 举报
回复
感谢分享
sohupc 2013-03-25
  • 打赏
  • 举报
回复
下载来编译运行有几个错误,求解答 ,谢谢 !
小小浣熊 2013-03-22
  • 打赏
  • 举报
回复
标记下,以后看,现在看不懂0.0
绿 2013-03-17
  • 打赏
  • 举报
回复
我觉得不管是怎么accept,瞬间连接量一大肯定会丢失的吧。 除非你是n多服务器同时accept那种。(只是猜想)
不懂必须要问 2013-03-12
  • 打赏
  • 举报
回复
好,准备下载。
lishaoyu 2013-03-11
  • 打赏
  • 举报
回复
引用 108 楼 iComputerLion 的回复:
本帖最后由 VisualEleven 于 2011-05-04 14:28:35 编辑 C/C++ code?12345678910111213141516171819202122232425262728#include "IOCPServer.h"#include <iostream>#include <stdio.h>using nam……
对于http协议来说,server响应客户端的请求之后,tcp链接随之关闭,所以获取的一直是0!
Luo_Bryant 2013-03-07
  • 打赏
  • 举报
回复
学习了。。。
liangbina07 2012-12-11
  • 打赏
  • 举报
回复
我也在学习中完成端口 mark一下。
jianghandaxue 2012-11-20
  • 打赏
  • 举报
回复
UP .......................
amyit 2012-11-15
  • 打赏
  • 举报
回复
顶起,学习一下,支持
ChinaTek 2012-09-05
  • 打赏
  • 举报
回复
收藏了,必须的
Lytton_jing 2012-08-16
  • 打赏
  • 举报
回复
正学习winsock,up
cohenzhao 2012-08-11
  • 打赏
  • 举报
回复
刚看了关于winsock 的5中i/o模型,正好需要了解一下IOCP。楼主好东西
zdleek 2012-08-08
  • 打赏
  • 举报
回复
mark一下,以备参考
加载更多回复(112)
一、物理架构说明 游戏系统组件包括: 服务器系统(中心服务器控制系统,服务器登陆控制系统,游戏登陆服务器,游戏房间控制系统,游戏组件系统),游戏客户端(游戏大厅,游戏组件)。 数据库系统:用于保存用户信息数据、游戏积分数据、游戏系统运行状态数据,系统日志数据等数据。 中心服务器控制系统:用于向客户端提供全局配置,初始化数据使用。 服务器登陆控制系统:用于房间服务控制系统登陆效验使用。 游戏房间控制系统:用于控制游戏房间的启动,停止,添加,删除,管理等。 游戏组件系统:用于具体游戏服务,被游戏房间控制系统挂接,提供游戏服务。 游戏大厅:游戏玩家连接游戏使用。 二、系统结构 系统选用的开发工具是优秀的Microsoft Visual C++.net2003,系统采用客户端/服务器(C/S)编程模式,TCP/IP协议作为客户端和服务器的通信网络层,运用具有性能最优的完成端口(IOCP:Input/Output Completion Port )网络开发模型搭建服务器软件.客户端采用WinSocket API作为网络层。 系统采用多服务器分布式架构,由一个中心服务器(CENTERSERVER),多个主服务器(MainServer)和多个从服务器(LocalServer)同时工作以实现游戏逻辑和用户管理及通讯的功能。中心服务器向客户端提供全局配置,初始化数据(主要是定位一个主服务器IP地址),主服务器管理客户端用户身份验证、登录以及管理从服务器的建立,由多个从服务器管理游戏通信,大厅及房间,从服务器可任意添加、删除、修改等。 网络棋牌游戏服务器架构全文共7页,当前为第1页。系统首先启动中心服务器(CENTERSERVER), 中心服务器从INI文件中读取MainServer列表信息, 客户端提供全局配置,初始化数据,然后等待客户联结, 客户联结后CENTERSERVER定位一个MainServer的IP地址和端口号,发往客户端, 客户端收到后断开CENTERSERVER的联接,并马上用MainServer的IP地址和端口号,和主服务器(MainServer)连接.主服务器从数据库中读取从服务器的所有信息到主服务器的内存。首先读取ComType表以建立所有的游戏类型的基本信息,然后读取ServiceInfo(界面树结点信息表)以获得包括客户端界面结构、从服务器的信息、大厅和房间的一切信息。当有客户端请求登录并成功和主服务器连接的时候,主服务器将这所有的信息一次性发到客户端内存,客户端根据这些信息生成界面结构树。 网络棋牌游戏服务器架构全文共7页,当前为第1页。 主服务器启动后还可以在主服务器里创建多个从服务器及房间,创建完成后从服务器的IP地址及端口号就作为它的唯一标识被同时写进数据库和主服务器的内存;房间号、房间所属的游戏类型、所属的从服务器号也作为房间的唯一标识被同时写进数据库和主服务器的内存。 从服务器创建以后就在它所属的机器上启动。 客户端登录后首先和主服务器建立连接(并且一直到客户端退出才断开)连接成功后生成界面结构树(前述),当用户点击某个游戏房间的时候系统从内存中读出这个房间的所有信息(前述),根据房间所属从服务器的IP地址及端口号试图和这个从服务器建立连接,连接成功后相应的从服务器就将这个房间的所有信息发到这个客户端,客户端收到以后就根据这些信息生成房间。每当有客户端的游戏位置发生改变的时候就向从服务器发送改变信息,从服务器保存、修改所有与它连接的客户端的位置信息列表。 当一张桌子坐满时游戏开始。游戏开始后客户端也是和从服务器通信以更新游戏信息。 当客户端退出游戏后就回到大厅的这个房间,当退出大厅的时候首先和从服务器断开连接,然后和主服务器断开连接,最后终止整个客户端程序。 三、模块结构 系统包括三大主要模块结构:MainServer,LocalServer,Com.此外还有客户端安装,更新模块等。在三大主要模块结构中还有子DLL(动态链接库)模块。 1、MainServer(EXE项目):封装主服务器功能,包括管理客户端用户身份验证、登录以及管理从服务器的建立,数据库读写等。 2、LocalServer(EXE项目):封装从服务器功能,包括管理客户端游戏通信,游戏逻辑,大厅及房间等。 3、Com(EXE项目):封装客户端所有功能,包括客户端登录,大厅及房间,客户端游戏通信,游戏逻辑等。Com包括以下子模块: 客户端通用库PubLib(DLL模块)封装了客户端通用的调用接口,控件,类。供客户端所有的模块调用. 麻将游戏通用库MJLib(DLL模块)封装了客户端麻将游戏通用的调用接口类和十堰麻将类。通用的调用接口类供特殊的麻将游戏模块调用。 网络棋牌游戏服务器架构全文共7页,当前为第2页。扑克牌游戏通用库PisaLib(D
第1 章 NetBIOS 1 1.1 Microsoft NetBIOS 2 1.1.1 LANA 编号 2 1.1.2 NetBIOS 名字 4 1.1.3 NetBIOS 特性 6 1.2 NetBIOS 编程基础 7 1.3 常规NetBIOS 例程 8 1.3.1 会话服务器:异步回调模型 15 1.3.2 会话服务器:异步事件模型 20 1.3.3 NetBIOS 会话客户机 24 1.4 数据报的工作原理 28 1.5 其他NetBIOS 命令 40 1.5.1 适配器状态 40 1.5.2 查找名字 42 1.5.3 将传送协议同LANA 编号对应起来 43 1.6 平台问题 43 1.6.1 Windows CE 44 1.6.2 Windows 9x 44 1.6.3 常规问题 44 1.7 小结 44 第2 章 重定向器 45 2.1 通用命名规范 45 2.2 多UNC 提供者 47 2.3 网络提供者 47 2.4 重定向器简介 48 2.5 服务器消息块 48 2.6 安全问题 49 2.6.1 安全描述符 49 2.6.2 访问令牌 51 2.7 网络安全 51 2.8 一个实例 52 2.9 小结 53 第3 章 邮槽 54 3.1 邮槽实施细节 54 3.1.1 邮槽的名字 54 3.1.2 消息的长度 55 3.1.3 应用程序的编译 56 3.1.4 错误代码 57 3.2 基本客户机/服务器 57 3.2.1 邮槽服务器的详情 57 3.2.2 邮槽客户机的详情 59 3.3 其他邮槽API 61 3.4 平台和性能问题 62 3.4.1 8.3 字符名字限制 62 3.4.2 不能取消“凝结”的I/O 请求 62 3.4.3 超时引起的内存废弃 64 3.5 小结 65 第4 章 命名管道 66 4.1 命名管道的实施细节 66 4.1.1 命名管道命名规范 67 4.1.2 字节模式及消息模式 67 4.1.3 应用程序的编译 67 4.1.4 错误代码 68 4.2 客户机与服务器的基础 68 4.2.1 服务器的细节 68 4.2.2 高级服务器的细节 74 4.2.3 客户机的细节 81 4.3 其他API 调用 83 4.4 平台和性能问题 86 4.5 小结 87 第二部分 Winsock API 第5 章 网络原理和协议 89 5.1 协议的特征 89 5.1.1 面向消息 89 5.1.2 面向连接和无连接 91 5.1.3 可靠性和次序性 91 5.1.4 从容关闭 92 5.1.5 广播数据 92 5.1.6 多播数据 92 5.1.7 服务质量 92 5.1.8 部分消息 93 5.1.9 路由选择的考虑 93 5.1.10 其他特征 93 5.2 支持的协议 93 5.2.1 支持的Win32 网络协议 93 5.2.2 Windows CE 网络协议 94 5.3 Winsock 2 协议信息 94 5.4 Windows 套接字 97 5.5 具体平台的问题 99 5.6 选择适当的协议 100 5.7 小结 100 第6 章 地址家族和名字解析 102 6.1 IP 102 6.1.1 TCP 102 6.1.2 UDP 102 6.1.3 定址 102 6.1.4 创建套接字 105 6.1.5 名字解析 105 6.2 红外线套接字 107 6.2.1 定址 107 6.2.2 名字解析 108 6.2.3 红外线设备列举 108 6.2.4 查询IAS 110 6.2.5 创建套接字 111 6.2.6 套接字选项 112 6.3 IPX/SPX 112 6.3.1 编址 112 6.3.2 创建套接字 112 6.4 NetBIOS 115 6.4.1 定址 115 6.4.2 创建套接字 116 6.5 AppleTalk 117 6.5.1 定址 117 6.5.2 AppleTalk 名的注册 118 6.5.3 AppleTalk 名的解析 119 6.5.4 创建套接字 124 6.6 ATM 124 6.6.1 定址 125 6.6.2 创建套接字 128 6.6.3 把套接字和SAP 绑定在一起 129 6.6.4 名字解析 130 6.7 Winsock 2 支持的其他函数 130 6.8 小结 131 ......

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧