【转】提高完成端口效率的几种有效方法

 
原文地址:http://blog.chinaunix.net/uid-20338068-id-1702742.html ;
提高完成端口效率的几种有效方法
1:使用AcceptEx代替accept。AcceptEx函数是微软的Winsosk 扩展函数,这个函数和accept的区别就是:accept是阻塞的,一直要到有客户端连接上来后accept才返回,而AcceptEx是异步的,直接就返回了,所以我们利用AcceptEx可以发出多个AcceptEx调用 等待客户端连接。另外,如果我们可以预见到客户端一连接上来后就会发送数据(比如WEBSERVER的客户端浏览器),那么可以随着AcceptEx投递一个BUFFER进去,这样连接一建立成功,就可以接收客户端发出的数据到BUFFER里,这样使用的话,一次AcceptEx调用相当于accpet和recv的一次连续调用。同时,微软的几个扩展函数针对操作系统优化过,效率优于WINSOCK 的标准API函数。 

2:在套接字上使用SO_RCVBUF和SO_SNDBUF选项来关闭系统缓冲区。这个方法见仁见智,详细的介绍可以参考《WINDOWS核心编程》第9章。这里不做详细介绍,我封装的类中也没有使用这个方法。 

3:内存分配方法。因为每次为一个新建立的套接字都要动态分配一个“单IO数据”和“单句柄数据”的数据结构,然后在套接字关闭的时候释放,这样如果有成千上万个客户频繁连接时候,会使得程序很多开销花费在内存分配和释放上。这里我们可以使用lookaside list。开始在微软的platform sdk里的SAMPLE里看到lookaside list,我一点不明白,MSDN里有没有。后来还是在DDK的文档中找到了,, 

lookaside list 

A system-managed queue from which entries of a fixed size can be allocated and into which entries can be deallocated dynamically. Callers of the Ex(ecutive) Support lookaside list routines can use a lookaside list to manage any dynamically sized set of fixed-size buffers or structures with caller-determined contents. 

For example, the I/O Manager uses a lookaside for fast allocation and deallocation of IRPs and MDLs. As another example, some of the system-supplied SCSI class drivers use lookaside lists to allocate and release memory for SRBs. 

    lookaside list名字比较古怪(也许是我孤陋寡闻,第一次看到),其实就是一种内存管理方法,和内存池使用方法类似。我个人的理解:就是一个单链表。每次要分配内存前,先查看这个链表是否为空,如果不为空,就从这个链表中解下一个结点,则不需要新分配。如果为空,再动态分配。使用完成后,把这个数据结构不释放,而是把它插入到链表中去,以便下一次使用。这样相比效率就高了很多。在我的程序中,我就使用了这种单链表来管理。 

    在我们使用AcceptEx并随着AcceptEx投递一个BUFFER后会带来一个副作用:比如某个客户端只执行一个connect操作,并不执行send操作,那么AcceptEx这个请求不会完成,相应的,我们用GetQueuedCompletionStatus在完成端口中得不到操作结果,这样,如果有很多个这样的连接,对程序性能会造成巨大的影响,我们需要用一种方法来定时检测,当某个连接已经建立并且连接时间超过我们规定的时间而且没有收发过数据,那么我们就把它关闭。检测连接时间可以用SO_CONNECT_TIME来调用getsockopt得到。 

    还有一个值得注意的地方:就是我们不能一下子发出很多AcceptEx调用等待客户连接,这样对程序的性能有影响,同时,在我们发出的AcceptEx调用耗尽的时候需要新增加AcceptEx调用,我们可以把FD_ACCEPT事件和一个EVENT关联起来,然后用WaitForSingleObject等待这个Event,当已经发出AccpetEx调用数目耗尽而又有新的客户端需要连接上来,FD_ACCEPT事件将被触发,EVENT变为已传信状态, WaitForSingleObject返回,我们就重新发出足够的AcceptEx调用。

 

### 回答1: 完成端口IOCP)是一种用于高性能和可伸缩网络应用程序的输入输出(IO)模型。完成端口基于事件驱动模型,能够处理大量并发连接,因此将Socket设置为异步是必要的。 异步Socket指的是通过异步操作来执行Socket通信,即发送和接收数据不会阻塞主线程,而是通过回调函数或事件处理程序来通知主线程数据的到达或发送的完成。 设置Socket为异步的好处有如下几点: 1. 提高性能:异步Socket允许应用程序在等待数据到达时执行其他操作,而不是被一次阻塞。这样可以充分利用系统资源,并提高网络应用程序的吞吐量和并发处理能力。 2. 增加可伸缩性:异步Socket允许处理大量并发连接而无需为每个连接创建一个线程。相比之下,同步Socket需要为每个连接创建一个线程,当并发连接数增加时,线程数量会呈指数级增长,导致系统资源消耗过大和性能下降。 3. 简化编程模型:异步Socket能够通过回调函数或事件处理程序来处理数据到达或发送完成的通知,这样可以简化编程模型,避免了繁琐的线程管理和同步机制。 总之,为了充分利用完成端口的高性能和可伸缩性特点,我们需要将Socket设置为异步。这样可以提高网络应用程序的性能、并发处理能力和可伸缩性,同时简化编程模型,使得应用程序更加高效和稳定。 ### 回答2: 完成端口(Completion Port)是一种在Windows平台上实现异步IO操作的机制。在使用完成端口时,可以使用异步套接字(Asynchronous Socket)来实现异步通信。 异步套接字是将套接字操作请求发送给操作系统后立即返回,而不等待操作完成的一种套接字编程方式。相比于同步套接字,异步套接字能够极大地提高系统的并发性能和响应速度。 完成端口完成套接字IO操作的一种机制,在异步通信中扮演着重要的角色。完成端口通过绑定到IOCP对象(IO Completion Port)上将套接字操作请求提交给操作系统进行处理。当套接字操作完成后,操作系统将通过调用注册的回调函数通知应用程序,从而实现套接字的异步操作。 设置套接字为异步模式,需要调用相关的API函数,如WSAIoctl或WSAEventSelect,并指定一个完成端口来处理套接字的异步操作。这样一来,套接字的读、写、连接等操作就可以在后台进行,而不会对主线程造成阻塞。同时,完成端口还允许应用程序同时处理多个套接字的异步操作,有效提高系统的吞吐量和并发性能。 总之,完成端口是一种能够实现异步套接字IO操作的机制,在并发性能和响应速度方面具有明显的优势。通过设置套接字为异步模式,并将其与完成端口绑定,可以实现套接字的异步操作,提升系统的性能和可扩展性。 ### 回答3: 完成端口(Completion Port)是一种多线程消息处理模式,常用于高效地处理大量并发的I/O操作。而在完成端口中,socket通信可以设置为异步操作。 在Socket通信中,传统上的阻塞式方式会导致一个线程一直等待I/O操作完成,无法同时执行其它任务,效率较低。而异步操作可以将I/O请求提交给操作系统后就立即返回,不需要等待操作完成。这样可以在等待数据传输的同时继续处理其他任务,提高系统的并发性能。 设置Socket为异步操作需要使用特定的函数和参数来完成。首先,通过调用CreateIoCompletionPort函数创建一个完成端口对象,并将Socket的句柄与其关联。然后,使用WSAIoctl或WSAEventSelect函数将Socket设置为非阻塞模式。接下来,使用专门的异步I/O函数(如WSASend、WSARecv)来发起异步操作,操作完成后会以消息的形式通知完成端口对象。可以通过GetQueuedCompletionStatus函数从完成端口中获取已完成的异步操作,并进行相应的处理。 异步Socket通信的优点是能够提高系统的并发性能,充分利用多核处理器的能力,并且能够更好地处理突发的大量请求。但是需要注意的是,异步编程相对于同步编程更为复杂,需要合理地管理资源和处理回调,以避免出现竞态条件、内存泄漏等问题。 总之,完成端口Socket通过设置为异步操作可以提高系统的并发性能,在处理大量并发的I/O操作时更为高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值