强大的TcpServer压力测试工具源码(附突破连接限制的方法和工具)

http://blog.csdn.net/guestcode/article/details/5756806

http://blog.csdn.net/guestcode/article/details/7538636

关键词:IOCP TcpServer TcpClient 完成端口 服务器 达到6万连接 突破连接限制 压力测试工具 堵塞锁 非堵塞锁 无锁 Lock Free 并发队列 并发可扩充环形队列

 

首先感谢在行动和精神上给予本人支持的各位同行,在过去的日子,使得本人的IOCP研究进入了崭新的领域。本文及附件希望能给予更多人的帮助,限于商用等原因,除了原来的0.85版开源之外,更高版本不便开源,仅简单描述一些技术要点,请谅解。但附件的压力工具源码,仍然能给予很多帮助,比如封包、解包、处理粘包等,同是压力工具还能帮助开发者测试服务器的性能,而且此帮助并不仅仅是一般的帮助。(其他的IOCP方法网上都有介绍,这里不多说。)

一、TcpServer

1、结构及流程


A、看守线程负责响应接受投递不足时的事件并投递接受请求,同是处理空连接和心跳超时

B、工作线程负责处理读写完成及读写错误的处理,并投递给处理线程

C、由于在工作处理数据及进行文件和数据库读写等操作可能会造成通信“卡”的现象,因此增加了处理线程,通过完成队列和线程池,接受工作线程投递过来的事件,处理线程通过回调函数将IO操作结果传递给应用层,应用层完全可以在回调函数里处理数据,从而实现了0拷贝功能,并保证数据的有序处理。

2、运行信息

为能更好的测试模块,开发者可参考截图的信息内容,对自己的模块进行测试开发工作,以帮助观察运行情况判断问题所在。



二、不可忽视的关闭工作

很多人在关闭通讯模块的时候,关闭所有连接和线程然后把记录的所有的内存都一一释放就结束了关闭工作。这样尽管没有内存泄露,但却可能隐蔽了其他问题。

正确的做法是:

1、关闭监听

2、关闭所有在线连接

3、等待关键计数器(内存池、连接池等使用计数器)归零 (这一步非常重要,这步过不了关肯定有问题)

4、关闭所有线程

5、逐一释放内存资源

6、变量复位

三、后IOCP时代

个人认为,微软的IOCP模型并不是Windows socket的终极,IOCP部分功能和效率仍然有待改进,以及Windows socket接口仍然不是高效率的体现,对开发有高要求的人,尤其是研究过Win2000源码的人,更深有体会。大家都知道,凡是满足功能强大的软件,效率在一定程度上会打折扣,针对高效率模型提供专有的Socket API才是关键,而不是一个API通用任何模型。微软到底是改进现有功能呢,还是提供更有效率的模型,这个只有微软才知道了。

四、IOCP的更高境界

入题前先给线程同步的锁分类:1、堵塞锁:系统提供的内核态的同步机制(内核态切换的效率众所周知),2.、非堵塞锁:诸如LockFree等使用原子操作指令完成的同步机制,3、无锁:堵塞锁、非堵塞锁之外的同步机制,确实的说是没有锁的机制。网络及书本上介绍的IOCP,常用做法都是使用堵塞锁的方式,打破传统思维才能获得创新。在过去的日子中,本人已经实现了非堵塞锁并发同步的IOCP模块。并根据IOCP Tcp Server的特殊情况,能在多线程下某些竞争的地方不使用锁亦能实现并发式同步的功能。这个模块实现,需要对IOCP Tcp Server的数据结构(主要是队列)进行深入分析,根据实时性、使用频率等归纳总结,判断出:哪些需要立即处理的,哪些可以暂缓处理而又不影响效率的,哪些需要锁的,哪些不需要锁的,哪些需要堵塞锁的,哪些不需要堵塞锁的,需要堵塞锁的能不能换个角度可以使用非堵塞锁来解决等。

五、附件

1、突破连接限制的注册表设置方法及工具

比较全面的介绍突破连接限制。

2、功能相当强大的压力测试工具的源码、G-TcpClient.Lib(限制版)

有助于开发者学习和制作测试压力测试工具,另有封包、解包、处理粘包等。G-TcpClient.Lib是限制版,主要是和压力工具配套方便学习压力工具源码。

3、堵塞锁模式的服务器Exe、堵塞锁模式的压力测试工具exe

有助于测试自己的服务器和客户端。压力测试工具单机可以达到6万连接,附有说明书。




 附件下载链接:
http://download.csdn.net/download/guestcode/2568402 -- 老版本1.1
http://download.csdn.net/download/guestcode/6841679 -- 新版本2.5

/******************************************************************************** * * * G-TcpClient:基于完成端口的Tcp客户端通讯模块(IOCP TcpClient) * * * * Copyright © 2009-2010 GuestCode 代码客(卢益贵) * * 版权所有 侵权必究 * * * * QQ:48092788 E-Mail:48092788@qq.com 源码博客:http://blog.csdn.net/guestcode * * * * GSN:34674B4D-1F63-11D3-B64C-11C04F79498E * * * ********************************************************************************/ #pragma once extern "C" { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 类型定义 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #ifndef _GTYPE #define _GTYPE typedef unsigned char* PGBUF; typedef void(__stdcall *PGFN_ON_CONNECTED)(unsigned int unPerHandle, unsigned char* pBuf, unsigned int unLen); typedef void(__stdcall *PGFN_ON_RECEIVED)(unsigned int unPerHandle, unsigned char* pBuf, unsigned int unLen); typedef void(__stdcall *PGFN_ON_SENDED)(unsigned int unPerHandle, unsigned int unSendID, unsigned int unLen); typedef void(__stdcall *PGFN_ON_DISCONNECTED)(unsigned int unPerHandle, unsigned int unFlag); typedef void(__stdcall *PGFN_ON_THREAD)(unsigned int unThreadContext, unsigned int unThreadHandle, unsigned int unThreadID, BOOL bIsBegin, unsigned int unFlag); /* typedef struct _CONNECTION { unsigned int unPerHandle; }CONNECTION, *PCONNECTION; typedef void(__stdcall *PGFN_ON_CONNECTED)(unsigned int unPerHandle, unsigned char* pBuf, unsigned int unLen); typedef void(__stdcall *PGFN_ON_RECEIVED)(PCONNECTION pConnection, unsigned char* pBuf, unsigned int unLen); typedef void(__stdcall *PGFN_ON_SENDED)(PCONNECTION pConnection, unsigned int unSendID, unsigned int unLen); typedef void(__stdcall *PGFN_ON_DISCONNECTED)(PCONNECTION pConnection, unsigned int unFlag); void __stdcall GTcpClt_OnThread(unsigned int unThreadContext, unsigned int unThreadHandle, unsigned int unThreadID, BOOL bIsBegin, unsigned int unFlag) { } void __stdcall GTcpClt_OnConnected(unsigned int unPerHandle, void* _NULL, unsigned int unNULL) { } void __stdcall GTcpClt_OnReceived(PCONNECTION pConnection, unsigned char* pBuf, unsigned int unLen) { } void __stdcall GTcpClt_OnSended(PCONNECTION pConnection, unsigned int unSendID, unsigned int unLen) { } void __stdcall GTcpClt_OnDisconnected(PCONNECTION pConnection, unsigned int unFlag) { } */ #define _USE_UNICODE 1 #ifndef _DLL //#define _DLL #endif #ifdef _DLL #define DllExport _declspec(dllexport) #else #define DllExport #endif #define VER_FLAG_WIDE_CHAR 0x01 #define VER_FLAG_BETA 0x02 #define VER_FLAG_ZERO_READ 0x04 #define VER_FLAG_TRIAL 0x08 #define VER_FLAG_DEBUG 0x10 #define HNDS_CONNECT 1 #define HNDS_CONNECTED 2 #define HNDS_DISCONNECT 3 #endif //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 类型定义 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 版本信息 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #if(_USE_UNICODE) DllExport wchar_t* __stdcall GTcpClt_GetVersionName(void); #else DllExport char* __stdcall GTcpClt_GetVersionName(void); #endif DllExport float __stdcall GTcpClt_GetVersionNumber(void); DllExport unsigned int __stdcall GTcpClt_GetVersionFlag(void); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 版本信息 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 功能函数 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllExport DWORDLONG __stdcall GTcpClt_GetPhyMemInfo(DWORDLONG* pdwTotal); #if(_USE_UNICODE) DllExport void __stdcall GTcpClt_WriteLog(wchar_t* pstrLog, unsigned int unCode = 0); DllExport void __stdcall GTcpClt_GetHostIP(wchar_t* pstrIP, unsigned int unLen, BOOL bIsInternetIP = FALSE); #else DllExport void __stdcall GTcpClt_WriteLog(char* pstrLog, unsigned int unCode = 0); DllExport void __stdcall GTcpClt_GetHostIP(char* pstrIP, unsigned int unLen, BOOL bIsInternetIP = FALSE); #endif //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 功能函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>> PerIoData函数 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllExport unsigned int __stdcall GTcpClt_GetGBufSize(void); DllExport unsigned int __stdcall GTcpClt_GetIoDataSize(void); DllExport unsigned int __stdcall GTcpClt_GetIoDataUse(void); DllExport unsigned int __stdcall GTcpClt_GetIoDataTotal(void); DllExport float __stdcall GTcpClt_GetIoDataUseRate(void); DllExport unsigned int __stdcall GTcpClt_GetIoDataUseMem(void); //<<<<<<<<<<<<<<<<<<<<<<<<<<<< PerIoData函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>> PerHndData函数 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllExport unsigned int __stdcall GTcpClt_GetHndDataUse(void); DllExport unsigned int __stdcall GTcpClt_GetHndDataTotal(void); DllExport unsigned int __stdcall GTcpClt_GetHndDataSize(void); DllExport float __stdcall GTcpClt_GetHndDataUseRate(void); DllExport unsigned int __stdcall GTcpClt_GetHndDataUseMem(void); //<<<<<<<<<<<<<<<<<<<<<<<<<<<< PerHndData函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 信息函数 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllExport unsigned int __stdcall GTcpClt_GetThreadNumber(void); DllExport unsigned int __stdcall GTcpClt_GetPageSize(void); DllExport unsigned int __stdcall GTcpClt_GetBlockSize(void); DllExport unsigned int __stdcall GTcpClt_GetConnectCount(void); DllExport unsigned int __stdcall GTcpClt_GetThreadRunCount(unsigned int unThreadContext); DllExport unsigned int GTcpClt_GetState(unsigned int unPerHandle); #if(_USE_UNICODE) DllExport wchar_t* __stdcall GTcpClt_GetThreadName(unsigned int unThreadContext); DllExport BOOL __stdcall GTcpSock_GetPerHandleInfo(unsigned int unPerHandle, wchar_t* pstrIP, unsigned int unIPLen, wchar_t* pstrPort, unsigned int unPortLen); DllExport BOOL __stdcall GTcpSock_GetPerHandleName(unsigned int unPerHandle, wchar_t* pstrName, unsigned int unLen); #else DllExport char* __stdcall GTcpClt_GetThreadName(unsigned int unThreadContext); DllExport BOOL __stdcall GTcpSock_GetPerHandleInfo(unsigned int unPerHandle, char* pstrIP, unsigned int unIPLen, char* pstrPort, unsigned int unPortLen); DllExport BOOL __stdcall GTcpSock_GetPerHandleName(unsigned int unPerHandle, char* pstrName, unsigned int unLen); #endif DllExport unsigned int __stdcall GTcpClt_GetProcesserNumber(void); DllExport BOOL __stdcall GTcpClt_IsActive(); DllExport unsigned int __stdcall GTcpClt_GetUseMem(void); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 信息函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 操作函数 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DllExport void* __stdcall GTcpClt_GetPerHandleOwner(unsigned int unPerHandle); DllExport BOOL __stdcall GTcpClt_SetPerHandleOwner(unsigned int unPerHandle, void* pOwner); DllExport PGBUF __stdcall GTcpClt_AllocGBuf(void); DllExport BOOL __stdcall GTcpClt_FreeGBuf(PGBUF pGBuf); DllExport unsigned int __stdcall GTcpClt_PostSendGBuf(unsigned int unPerHandle, PGBUF pGBuf, unsigned int unLen); DllExport unsigned int __stdcall GTcpClt_PostSendBuf(unsigned int unPerHandle, unsigned char* pBuf, unsigned int unLen); DllExport void __stdcall GTcpClt_PostBroadcast(unsigned char* pBuf, unsigned int unLen); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 操作函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 主要函数 DllExport BOOL __stdcall GTcpClt_CloseConnect(unsigned int unPerHandle); #if(_USE_UNICODE) DllExport unsigned int __stdcall GTcpClt_OpenConnect( wchar_t* pstrRemoteIP, wchar_t* pstrRemotePort, wchar_t* pstrLocalIP, PGFN_ON_CONNECTED pfnOnConnected, PGFN_ON_RECEIVED pfnOnReceived, PGFN_ON_SENDED pfnOnSended, PGFN_ON_DISCONNECTED pfnOnDisconnected, void* pOwner = NULL); #else DllExport unsigned int __stdcall GTcpClt_OpenConnect( char* pstrRemoteIP, char* pstrRemotePort, char* pstrLocalIP, PGFN_ON_CONNECTED pfnOnConnected, PGFN_ON_RECEIVED pfnOnReceived, PGFN_ON_SENDED pfnOnSended, PGFN_ON_DISCONNECTED pfnOnDisconnected, void* pOwner = NULL); #endif DllExport BOOL __stdcall GTcpClt_Start(unsigned int unHeartbeatTime = 60, unsigned int unMaxNetDelayTime = 5, unsigned int unGuardThreadSleepTime = 2, PGFN_ON_THREAD pfnOnThread = NULL, unsigned int unHndDataInitNumber = 1000, unsigned int unIoDataInitNumber = 1500, unsigned int unProcesserThreadNumber = 0, unsigned int unWorkerThreadNumber = 0); DllExport void __stdcall GTcpClt_Stop(void); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 主要函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< } /* ... extern "C" */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值