当前位置:首页 > 代码 > 正文

iocp源代码(iocp详解)

admin 发布:2022-12-20 00:23 107


本篇文章给大家谈谈iocp源代码,以及iocp详解对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

求助,IOCP代码中的内存泄露问题

当然不会,所谓内存泄露一般是指一个进程在运行的过程中不断申请内存,但是没有释放。当该进程结束之后,它所占用的所有资源(当然包括内存)会自动被操作系统回收的。

有人能说清楚JAVA7 NIO NETTY IOCP之间的联系吗

早期网络访问的做法是,连接以后,就等待对方应答,对方没有应答,代码就会死在那里。这称为阻塞式通讯。

后来,java 1.4 开始引入了nio, nio是非阻塞式网络通讯. 其实可以理解为系统去扫描端口,如果有返回就处理,没有的话,代码就继续做别的事。

不过nio的编码比较麻烦,虽然性能好,可是很多代码还在用阻塞,因为代码简单,很多例子上也是socket的。

然后高丽人开发了apache的mina,可以快速开发nio。

后来高丽人离开apache,开发了netty,提供了另一种调用nio的framework。

现在mina和netty是最常用的nio框架。

至于iocp,这个是个系统级的实现,其实类似nio,不过是通过操作系统来实现的。而且只支持windows。java 7以后把iocp引入,提供了快速开发的接口。不过不是很推荐使用。系统实现就表示iocp不再是跨平台的。那么实用性就差很多了。

为什么我用VC6.0要编译ghost源码都不能编译成功?

无法打开MSTcpIp.h看一下是include

\"\"

照样include

然后本身把头文件放到文件夹里再编译

为什么完成端口是win

1. 完成端口的实质

个人感觉完成端口就是一个“闹钟”,它可以被当做任何事情的提醒设备。比如说,(没有试过)ReadFile可以异步操作,可以将这个异步操作的完成这个事件的提醒交给完成端口来完成。所以,原文中所使用的完成端口,只是将这个“闹钟”用在了网络传输的提醒上。这也就说明了,尽管我们可以使用完成端口来完成各种提醒,但是主框架仍然是Socket那套流程。

为了更清晰地表达,请看下面的描述(从上往下)。这是作者的代码的API调用流程。其实我不太喜欢作者的第三部分的那些流程图,因为其中用了太多的自定义函数而掩盖了底层的API调用。现在我把他还原。

初始化库,WSAStart()

创建完成端口,CreateIoCompletionPort(-1,...);

创建工作线程,CreateThread()

创建listen socket,WSASocket

绑定listen socket 至完成端口,CreateIoCompletionPort(socket, …)

listen socket与本地端口绑定 ,bind()

开始监听,listen()

向listen socket投递accept请求,AcceptEx()

干其他事情或者等待结束命令

通信结束,通知Worker线程们退出,PostQueuedCompletionStatus()

至于Working 线程的做法和原先一样。

可以看到,尽管我们说完成端口的性能是最好的,然而它只是一个时间走得特别准的“闹钟”而已。 网络编程的基本框架还是原来的那套。

2. 关于Accept投递和WSARev投递

整偏博文里我看得最头痛的就是这个“投递”。它到底是什么?

刚才说了,这里只是把完成端口作为“提醒”机制。具体来说,就是listen之后,通常的调用是如下面所示的

While(1)

{

Socket = Accept();

_beginthreadex(…); // 传入socket

}

只不过,这样的调用就是阻塞型调用。而使用完成端口的话,就是将这个Accept(当然,源代码中使用更复杂的AcceptEx,其实差不多的)的调用(其实在内部,就相当于一个要求被accept的请求)委托给完成端口,然后主线程马上返回,并且让后者来提醒之前已经创建好的、在线程函数中调用了GetQueuedCompletionStatus函数的某个线程。当然,至于是哪个线程拿到了,那就是系统调度问题,这对我们来说是黑盒的。这就是那个AcceptEx投递的含义了。说得通俗点,所谓的Accept投递,就是告诉完成端口,“我——listen socket,向你提交一个请求,如果你有客户端的连结请求了,请立即告诉我”。所以可以说,AcceptEx投递就是listen socket的一个IO请求而已。

同样的道理,如果我们不是让完成端口去通知Accept完成,而是去让它通知Receive操作完成,那就是原文中的“投递WSARev操作”了。显然,这是两种操作。

3. 关于工作线程中的一些关键点

那么作者在“详细”那一节第六步中说的那个难点是怎么回事呢?我的理解是这样的。负责监听完成端口的线程(就是之前已经创建好的、在线程函数中调用了GetQueuedCompletionStatus函数的某个线程),它们是在GetQueuedCompletionStatus返回之前是不知道到底是那个操作被“闹钟”了,再加上之前说过的,具体是哪个线程被“闹钟”是我们所不知道的。所以说,你根本就无法判断某个线程会被用做干嘛。所以就需要一种机制来分别了。作者采用的方法是,自定义一些说明性的信息,然后在投递的时候附带送过来,这样在接受的时候就可以通过这些附加信息加以区别了。这就是那个PER_SOCKET_CONTEXT和PER_IO_CONTEXT的作用了。

具体来说,如果是为投递Accept而准备的闹钟,那么某个线程GetQueuedCompletionStatus返回之后,将会获得和Accept投递有关的Socket和此请求的附加信息。和accept投递有关的socket是哪个呢?自然是用于做listen的那个socket(GetQueuedCompletionStatus函数的第三个参数返回它的上下文——其实就是一个和它相匹配的补充性结构,那是在将socket和完成端口绑定时传入的第三个参数)。

注意到一个socket上面可以有很多个请求(类比一个客户端/服务器连结上可以发送多次数据,每一次发送数据都需要通过一个“发送数据请求”),从而在listen socket上面,我们之前投递了多个acceptEx请求,那么到底是哪个请求到来了呢?其实对于AcceptEx请求而言,哪一个并不那么重要,反正大家的工作都是创建一个客户端/服务器连结socket,然后进行通信。然而如果真的重要了,那么就需要这个值了(比如说不同连结需要不同操作之类)。具体来说,GetQueuedCompletionStatus

倒数第二个参数OVERLAPPED*,返回的就是和这个请求相关的信息。它其实就是我们在投递这个请求的时候所附加给完成端口的说明性材料。注意看,这是一个OVERLAPPED结构指针,应该和我们自定义的PER_IO_CONTEXT没有关系。实则不然,回顾CIOCPModel::_PostAccept里面AcceptEx调用的最后一个参数实际上是,pAcceptIoContext-m_Overlapped。也就是说这里传回来的是PER_IO_CONTEXT的第一个成员m_Overlapped的地址。通过位于_WorkThread函数中的风骚宏CONTAINING_RECORD

就能够得到这个PER_IO_CONTEXT的首地址啦。

另外,如果投递的是WSARev请求呢?这个附加信息怎么穿进去?一样的啦,就是通过WSARev函数的OVERLAPPED结构体参数。这个结构体的实际作用,就是在异步IO操作之后,提供给你一些信息的。我们可以通过继承这个结构(或者和这里的做法一致——采用风骚宏CONTAINING_RECORD)来拓展它,让它包含我们需要的信息。

接下去的事情就好办了,根据自定义结构PER_IO_CONTEXT的成员m_OpType了解一些信息,知道这个回应,到底是listen socket的accept请求的回应(ACCEPT_POSTED)还是真正的客户端/服务器连结socket的发送或者接收请求的回应(RECV_POSTED和SEND_POSTED)。

如果是对accept请求的回应,那么返回的socket context和io context都是这个accept请求的,所以作者强调在_DoAccept中是一定不能够动这两个结构的。然而,如果是普通连结的发送/接收请求的回应,那么当然就是另外一回事情了。

关于iocp源代码和iocp详解的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://ahzz.com.cn/post/31986.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载