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的理解可能还不是那么好,组件难免回有问题,也请大家多多指教。
...全文
23422 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)

18,356

社区成员

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

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