没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
思考
在前一篇文章《WinSock2
编程之打造完整的
SOCKET
池 》中,介绍了 WinSock2 的一些新
函数,并重点详细介绍了什么是 SOCKET 池,有了这个概念,现在就接着展开更深入的讨论。
首先这里要重点重申一下就是,SOCKET 池主要指的是使用面向连接的协议的情况下,最常用
的就是需要管理大量的 TCP 连接的时候。常见的就是 Web 服务器、FTP 服务器等。
下面就分步骤的详细介绍如何最终实现 SOCKET 池。
一、WinSock2 环境的初始化:
要使用 WinSock2 就需要先初始化 Socket2.0 的环境,不废话,上代码:
WSADATA wd = {0};
int iError = WSAStartup(MAKEWORD(2,0), &wd);
if( 0 != iError )
{//出现错误,最好跟踪看下错误码是多少
return FALSE;
}
if ( LOBYTE(lpwsaData->wVersion) != 2 )
{//非 2.0 以上环境 退出了事 可能是可怜的 WinCE 系统
WSACleanup();
return FALSE;
}
最后再不使用 WinSock 之后都要记得调用一下 WSACleanup()这个函数;
二、装载 WinSock2 函数:
上一篇文章中给出了一个装载 WinSock2 函数的类,这里分解介绍下装载的具体过程,要提醒
的就是,凡是类里面演示了动态装载的函数,最好都像那样动态载入,然后再调用。以免出现
上网发帖跪求高手赐教为什么 AcceptEx 函数无法编译通过等问题。看完这篇文章详细你不会
再去发帖找答案了,呵呵呵,好了,上代码:
//定义一个好用的载入函数 摘自 CGRSMsSockFun 类
BOOL LoadWSAFun(GUID&funGuid,void*& pFun)
{//本函数利用参数返回函数指针
DWORD dwBytes = 0;
pFun = NULL;
//随便创建一个 SOCKET 供 WSAIoctl 使用 并不一定要像下面这样创建
SOCKET skTemp = ::WSASocket(AF_INET,
SOCK_STREAM, IPPROTO_TCP, NULL,
0, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == skTemp)
{//通常表示没有正常的初始化 WinSock 环境
return FALSE;
}
::WSAIoctl(skTemp, SIO_GET_EXTENSION_FUNCTION_POINTER,
&funGuid,sizeof(funGuid),&pFun,
sizeof(pFun), &dwBytes, NULL,NULL);
::closesocket(skTemp);
return NULL != pFun;
}
//演示如何动态载入 AcceptEx 函数
......
LPFN_ACCEPTEX pfnAcceptEx; //首先声明函数指针
GUID GuidAcceptEx = WSAID_ACCEPTEX;
LoadWSAFun(GuidAcceptEx,(void*&)pfnAcceptEx); //载入
......
//使用丰富的参数调用
......
pfnAcceptEx(sListenSocket,sAcceptSocket,lpOutputBu@er,
dwReceiveDataLength,dwLocalAddressLength,dwRemoteAddressLength,
lpdwBytesReceived,lpOverlapped);
//或者:
SOCKET skAccept = ::WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,
NULL, 0,WSA_FLAG_OVERLAPPED);
PVOID pBuf = new BYTE[sizeof(sockaddr_in) + 16];
pfnAcceptEx(skServer, skAccept,pBuf,
0,//将接收缓冲置为 0,令 AcceptEx 直接返回,防止拒绝服务攻击
sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, NULL,
(LPOVERLAPPED)pAcceptOL);
......
以上是一个简单的演示,如何动态载入一个 WinSock2 扩展函数,并调用之,其它函数的详细
例子可以看前一篇文章中 CGRSMsSockFun 类的实现部分。如果使用 CGRSMsSockFun 类
的话当然更简单,像下面这样调用即可:
CGRSMsSockFun MsSockFun;
MsSockFun.AcceptEx(skServer, skAccept,pBuf,
0,//将接收缓冲置为 0,令 AcceptEx 直接返回,防止拒绝服务攻击
sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, NULL,
(LPOVERLAPPED)pAcceptOL);
如果要使用这个类,那么需要一些修改,主要是异常处理部分,自己注释掉,或者用其它异常
代替掉即可,这个对于有基础的读者来说不是什么难事。
三、定义 OVERLAPPED 结构:
要想“IOCP”就要自定义 OVERLAPPED,这是彻底玩转 IOCP 的不二法门,可以这么说:“江湖
上有多少种自定义的 OVERLAPPED 派生结构体,就有多少种 IOCP 的封装!”
OVERLAPPED 本身是 Windows IOCP 机制内部需要的一个结构体,主要用于记录每个 IO 操
作的“完成状态”,其内容对于调用者来说是没有意义的,但是很多时候我们把它当做一个“火车
头”,因为它可以方便的把每个 IO 操作的相关数据简单的“从调用处运输到完成回调函数中”,这
是一个非常有用的特性,哪么如何让这个火车头发挥运输的作用呢?其实很简单:让它成为一
个自定义的更大结构体的第一个成员。然后用强制类型转换,将自定义的结构体转换成
OVERLAPPED 指针即可。当然不一定非要是新结构体的第一个成员,也可以是任何第 n 个成
员,这时使用 VC 头文件中预定义的一个宏 CONTAINING_RECORD 再反转回来即可。
说到这里一些 C++基础差一点的读者估计已经很头晕了,更不知道我再说什么,那么我就将
好人做到底吧,来解释下这个来龙去脉。
首先就以我们将要使用的 AcceptEx 函数为例子看看它的原型吧(知道孙悟空的火眼金睛用来
干嘛的吗?就是用来看原型的,哈哈哈):
BOOL AcceptEx(
__in SOCKET sListenSocket,
__in SOCKET sAcceptSocket,
__in PVOID lpOutputBu@er,
__in DWORD dwReceiveDataLength,
__in DWORD dwLocalAddressLength,
__in DWORD dwRemoteAddressLength,
__out LPDWORD lpdwBytesReceived,
__in LPOVERLAPPED lpOverlapped
);
剩余15页未读,继续阅读
资源评论
- xian_wwq2013-05-10有参考价值,不过在实践中,发现重复使用socket会有参数错误的异常抛出,不知道问题在哪里
- hero_yyh2013-04-10不错,可读性好。有帮助
蜗牛凯
- 粉丝: 14
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功