参考:http://www.codeproject.com/internet/iocp_server_client.asp
IOCP解决一个线程服务一个客户端的问题
要使用IOCP,你得做三件事:
1.将一个SOCKET与一个完成端口关联
2.处理异步IO调用
3.同步线程

取得异步IO的结果,你得传递两个参数:CompletionKey,OVERLAPPED
CompletionKey--DWORD  你可以通过它传递唯一的值,一般情况下,它是一个指针,指向一个结构或类,包含一些客户端的一些信息
OVERLAPPED--结构 通常用来传递内存缓冲区以用于异步IO调用

调用PostQueuedCompletionStatus进行异步IO调用
调用GetQueuedCompletionStatus进行线程同步

4个IOCP常遇到的问题及解决方案
WSAENOBUFS错误,通常会以为是普通的死锁及内存泄漏
对服务器进行压力测试可能会出现这个错误
--解决方法:调用WSARead读取0字节缓冲区,当调用完成,我们知道有数据进入了TCP/IP栈
,然后通过调用几个异步WSARead(MAXIMUMPACKAGESIZE最大包字节)
这个方法锁定内存当数据到达时,解决了WSAENOBUFS这个错误,但是这个方法减少了服务器的数据吞吐量


包重排序问题
解决方案:添加序数到缓冲类中
在接收及发送中进行包排序


异步未决读取和大块字节处理问题
大部份的服务协议是以包为基础的协议,在包的开始X字节为头部,在头部包含了整个包的长度详情
大块字节流可能包含一个和几个通信包,也可能只包含包的一部份


存取异常
相对于IOCP的专属问题,这算是小问题了
当客户端连接丢失,并且IO调用反回一个错误标志,那么这个客户端已经死掉了
在CompletionKey,这是一个指针,包含了客户端的相关数据,如果我们释放它占用的内存,那么当其它的IO调用从相同的客户端
返回错误标志,当我们将CompletionKey转换为指针,尝试访问或者删除它时,这时将发生存取异常

解决方案:添中一个记数到结构中,这个记数包含了有多少未决的IO调用,然后当我们删除这个结构时,如果这个数为0,表明没有IO调用再需要它了


一些经验技巧
1不要在没有锁定的情况下就对ClientContext进行读取与写入
2避免或特别小心死锁

pContext-> m_ContextLock.Lock();
//… code code ..
pContext2-> m_ContextLock.Lock();
// code code..
pContext2-> m_ContextLock.Unlock();
// code code..
pContext-> m_ContextLock.Unlock();
上面这段代码可有造成死锁

3不要在通知函数之外存取ClientContext,除非你用临界区将其包起来

 

posted @ 2007-04-02 22:11 三毛 阅读(4245) 评论(1) 编辑
今天是到新公司上班的第一天,新环境,新同事,新工作,呵呵,一切都是新的,这里是我人生新的起点,也是技术上的一个飞越,我想在这里一定会对我以后的人生有着重要的影响.新一天,看了一天的文档,codeproject上的两篇关于IOCP的文章,全是E文的,我的E文虽然有点差,但是看这些开发文档还是没什么问题的,一天,收获不少,让我了解到了IOCP的所有细节的东西,网络编程的底层,也让我的英文单词量上升了不少,嘿嘿,不过唯一让我感到不适应的就是,中午不能睡觉,下午4点左右的时候,我感到好困哦,好想睡哦,不过我还是克服住了,我想在这里每天都这样就好了,以后的技术绝对是顶瓜瓜的.
posted @ 2007-04-02 22:01 三毛 阅读(88) 评论(0) 编辑