你的位置:pcMing工作室 >> 资讯 >> 编程开发 >> C++编程 >> 详细内容 在线投稿

Winsock 完成端口模型简介

排行榜 收藏 打印 发给朋友 举报 来源: 互联网   发布者:未知
热度1211票  浏览419次 【共0条评论】【我要评论 时间:2010年4月08日 19:56

[.e0O` ]LlN0

#m}+~\6Qc!RD0o0三、单句柄数据和单I/O操作数据
Ns&bEy-Oc0一个工作者线程从GetQueuedCompletionStatus这个API调用接收到I/O完成通知后,在lpCompletionKey和lpOverlapped参数中,会包含一些必要的套接字信息。利用这些信息,可通过完成端口,继续在一个套接字上的I/O处理。通过这些参数,可获得两方面重要的套接字数据:单句柄数据,以及单I/O操作数据。其中, lpCompletionKey参数包含了“单句柄数据”,因为在一个套接字首次与完成端口关联到一起的时候,那些数据便与一个特定的套接字句柄对应起来了。这些数据正是我们在进行CreateIoCompletionPort API调用的时候,通过CompletionKey参数传递的。如早先所述,应用程序可通过该参数传递任意类型的数据。通常情况下,应用程序会将与I/O 请求有关的套接字句柄保存在这里。lpOverlapped参数则包含了一个OVERLAPPED结构,在它后面跟随“单I/O操作数据”。我们的工作者线程处理一个完成数据包时(将数据原封不动打转回去,接受连接,投递另一个线程,等等),这些信息是它必须要知道的。单I/O操作数据可以是追加到一个 OVERLAPPED结构末尾的、任意数量的字节。假如一个函数要求用到一个OVERLAPPED结构,我们便必须将这样的一个结构传递进去,以满足它的要求。要想做到这一点,一个简单的方法是定义一个结构,然后将OVERLAPPED结构作为新结构的第一个元素使用。举个例子来说,可定义下述数据结构,实现对单I/O操作数据的管理:
$`DwT(@,b{?'d0pcMing工作室7~EcCf

typedef struct
,DQ,e4L.F(Wyl!Y0{
#XBW!CRw3R9l+NS0    OVERLAPPED Overlapped;pcMing工作室4j4Gc%k:e6az ]
    WSABUF     DataBuf;pcMing工作室j]eeOB
    CHAR       Buffer[DATA_BUFSIZE];
2\HGd-HxdY0    BOOL       OperationType;
sLk'Ks3u0Ut0}PER_IO_OPERATION_DATA
pcMing工作室5dB)z ^cAr
该结构演示了通常要与I/O操作关联在一起的某些重要数据元素,比如刚才完成的那个I/O操作的类型(发送或接收请求)。在这个结构中,我们认为用于已完成 I/O操作的数据缓冲区是非常有用的。要想调用一个Winsock API函数,同时为其分配一个OVERLAPPED结构,既可将自己的结构“造型”为一个OVERLAPPED指针,亦可简单地撤消对结构中的 OVERLAPPED元素的引用。如下例所示:
6P/oK`G(a}]0
PER_IO_OPERATION_DATA PerIoData;
|`Kx6COi/l D0// 可像下面这样调用一个函数pcMing工作室v4wi6e^+Z
  WSARecv(socket, ..., (OVERLAPPED *)&PerIoData);pcMing工作室AQ)V(D9Hf'gH
// 或像这样
,To]#U$J0  WSARecv(socket, ..., &(PerIoData.Overlapped));

zK R.l7g!Mt0在工作线程的后面部分,等GetQueuedCompletionStatus函数返回了一个重叠结构(和完成键)后,便可通过撤消对 OperationType成员的引用,调查到底是哪个操作投递到了这个句柄之上(只需将返回的重叠结构造型为自己的 PER_IO_OPERATION_DATA结构)。对单I/O操作数据来说,它最大的一个优点便是允许我们在同一个句柄上,同时管理多个I/O操作(读 /写,多个读,多个写,等等)。大家此时或许会产生这样的疑问:在同一个套接字上,真的有必要同时投递多个I/O操作吗?答案在于系统的“伸缩性”,或者说“扩展能力”。例如,假定我们的机器安装了多个中央处理器,每个处理器都在运行一个工作者线程,那么在同一个时
-k*pB'vI0候,完全可能有几个不同的处理器在同一个套接字上,进行数据的收发操作。

HB+g5k v&u9YMMgp0最后要注意的一处细节是如何正确地关闭I/O完成端口—特别是同时运行了一个或多个线程,在几个不同的套接字上执行I/O操作的时候。要避免的一个重要问题是在进行重叠I/O操作的同时,强行释放一个OVERLAPPED结构。要想避免出现这种情况,最好的办法是针对每个套接字句柄,调用closesocket函数,任何尚未进行的重叠I/O操作都会完成。一旦所有套接字句柄都已关闭,便需在完成端口上,终止所有工作者线程的运行。要想做到这一点,需要使用PostQueuedCompletionStatus函数,向每个工作者线程都发送一个特殊的完成数据包。该函数会指示每个线程都“立即结束并退出”。下面是PostQueuedCompletionStatus函数的定义:
M"xL4I0l+R x!i$iS0pcMing工作室0B/S!AW1f*Y,A%O

BOOL PostQueuedCompletionStatus(
K!\/k$Q0R0u*e&i0    HANDLE CompletionPort,pcMing工作室jDJ!cr3h
    DWORD dwNumberOfBytesTransferred,pcMing工作室{9a Z'cY+p
    ULONG_PTR dwCompletionKey,pcMing工作室u y(k9q.h[
    LPOVERLAPPED lpOverlappedpcMing工作室4s7Ll,q+H1d
);

2xU K2e2Xt(F.a;hA0
7B#rD*j] Z]L:h6O0其中,CompletionPort参数指定想向其发送一个完成数据包的完成端口对象。而就dwNumberOfBytesTransferred、 dwCompletionKey和lpOverlapped这三个参数来说,每一个都允许我们指定一个值,直接传递给 GetQueuedCompletionStatus函数中对应的参数。这样一来,一个工作者线程收到传递过来的三个 GetQueuedCompletionStatus函数参数后,便可根据由这三个参数的某一个设置的特殊值,决定何时应该退出。例如,可用 dwCompletionPort参数传递0值,而一个工作者线程会将其解释成中止指令。一旦所有工作者线程都已关闭,便可使用CloseHandle函数,关闭完成端口,最终安全退出程序。pcMing工作室-O,wSE0\b ^

pcMing工作室DUe$w?E%f J6v^8u

顶:56 踩:65
对本文中的事件或人物打分:
当前平均分:-0.27 (369次打分)
对本篇资讯内容的质量打分:
当前平均分:-0.41 (347次打分)
【已经有374人表态】
58票
感动
46票
路过
54票
高兴
40票
难过
33票
搞笑
44票
愤怒
51票
无聊
48票
同情
上一篇 下一篇
发表评论
换一张

网友评论仅供网友表达个人看法,并不表明本网同意其观点或证实其描述。

查看全部回复【已有0位网友发表了看法】

网络资源