<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>
本文作者:sodme 本文出处:http://blog.csdn.net/sodme
版权声明:本文可以不经作者同意任意转载,但转载时烦请保留文章开始前两行的版权、作者及出处信息。
对于初次使用IOCP进行高性能服务器开发的朋友来说,可能会经常遇到一些莫名其妙的错误,让自己无从下手。为此,我将利用此篇文章对IOCP开发中的常见问题予以集中记录并持续添加,并附上我的处理建议,以供大家参考。
1、在程序创建监听套接字时,使用socket函数创建一个套接字时,总是报“INVALID_SOCKET”错误?
原因:出现此问题的原因,很可能是因为没有正确执行WSAStartUp函数引起的;
解决方法:请检查,是否使用WSAStartUp对winsock进行了初始化工作?如果进行了初始化,请检查初始化是否成功?
2、使用WSASend或WSARecv投递相应的发送或接收请求后,始终没有收到相应的GET函数完成返回通知?
原因:出现此问题的原因,绝大多数是因为函数参数没有进行正确的赋值。
解决方法:在执行wsasend和wsarecv操作前,请先将overlapped结构体使用memset进行清零。一个正确的调用格式如下:
[发送操作]
DWORD ByteSend=0;
DWORD Flags=0;
int tmpResult=0;
......
PPerHandleData tmpData;
......
memset(&(tmpData->Overlapped), '/0', sizeof(OVERLAPPED));//将overlapped结构清空
tmpData->Statu = ssSend;
tmpResult = WSASend(tmpData->socket, &(tmpData->WSASendBuffer), 1,
&ByteSend,
Flags,
&(tmpData->Overlapped),
NULL);
[接收操作]
DWORD byteRecv=0;
DWORD Flags=0;
int tmpResult=0;
......
PPerHandleData myHandlData;
......
memset(&(myHandlData->Overlapped), '/0', sizeof(OVERLAPPED));
memset(myHandlData->RecvBuffer, '/0', CLIENT_BUFFER_SIZE);
myHandlData->WSARecvBuffer.buf = myHandlData->RecvBuffer;
myHandlData->WSARecvBuffer.len = CLIENT_BUFFER_SIZE;
myHandlData->socket = myClient->m_ClientSocket;
myHandlData->Statu = ssRecv;
tmpResult = WSARecv(myHandlData->socket, &(myHandlData->WSARecvBuffer), 1, (LPDWORD)&byteRecv, (LPDWORD)&Flags, (LPWSAOVERLAPPED)&(myHandlData->Overlapped), 0);
3、当投递了一个WSARecv或WSASend请求后,总是返回“ERROR_IO_PENDING”错误?
原因:“ERROR_IO_PENDING”,表示的是WSARecv或WSASend操作正在执行中,还没有执行完毕。
解决方法:此错误可以直接忽略,如果参数设置正确,当操作完成时,系统会通过GET函数返回执行的形式来通知发送或接收操作已经完成。
4、为什么投递一个WSASend操作后,在Get函数中,获得发送完成事件的通知时,截获到的发送出去的数据却不是刚刚投递的数据?
原因:在投递WSASend时,会要求你指定数据缓冲区的地址,如果你此处的地址是通过new动态分配的,并且在投递过WSASend之后随之即delete了此空间,则可能会发生你的描述的这个现象。我的理解是:当WSASend操作还没有真正完成时,如果释放了数据缓冲区,那么WSASend将会因为缓冲区的释放而造成没有正确投递缓冲区内的数据,也就是说,WSASend在投递一个数据时,并没有即刻把数据拷到投递缓冲区去,如果是在WSASend完成后再释放此空间则不会发生这种情况。
5、一个误解: 单个服务器程序可承受最大连接数“理论”上是“65535”
请注意,这里有两个词分别被我标记上了引号,一个是“理论”,一个是“65535”。强调“理论”这个词,是想特别明确误解者的意思:就是说,这个值是不可能被打破的,是铁板钉丁的。而65535这个数字的由来,很多人想当然地将它与port最大值联系起来。的确,TCP的端口数,最大值确实为65535。但是,这并不代表一个服务器可以接受的连接数就是这个值,很多人之所以把这两个概念搞混淆是因为对socket和port没有更深的认识和理解。我们先来回想一下服务器服务的先后过程:服务器创建监听socket->与对外服务的端口号绑定->开始listen->客户端连接到服务器对应的port->服务器accept为新的客户端产生新的socket->基于这个新的socket与客户端交换数据。从以上流程来看,最大值为65535的“端口号”这个重要的东东,我们只用了一次,就是执行bind的时候!而以后创建的socket,说白了就是一个可以进行网络IO操作的HANDLE而已,它跟端口号的牵扯仅限bind以及作为客户端连接服务器的识别端口号的时候,一旦accept产生了socket,这个端口号,对服务器和新客户端的通信而言就不再有任何意义。而服务器可承载的连接数最大量,不就是能产生多少个客户端的socket吗?这个socket值即使与端口号无关,又何来65535的“理论”上限?我再一次地将“理论”二字用引号括起,是因为在有的操作系统中,默认的配置会将socket最大值设定为65535,但这个值是可以改的!
分享到:
相关推荐
windows socket网络编程之iocp完成端口模型的例子
手把手教你玩转网络编程模型之完成端口(CompletionPort)篇[归纳].pdf
想学习windows网络编程技术,这篇奇文一定不能错过哦!
PiggyX,拿走不谢。
JAVA网络编程: 编写的端口扫描器, 可以扫描本机和指定IP的端口
高性能网络编程--IO 完成端口
c# 源码,网络编程,端口扫描,可以扫描计算机打开的端口和没打开的端口
这份代码是我博客里的文章《完成端口详解 - 手把手教你玩转网络编程系列之三》的配套代码 里面的代码包括VC++2008/VC++2010编写的完成端口服务器端的代码,还包括一个对服务器端进行压力测试的客户端,都是经过我...
完成端口I/O模型编程完成端口I/O模型编程完成端口I/O模型编程完成端口I/O模型编程
步骤一,创建一个完成端口 步骤二判断有多少个处理器 步骤三:根据处理器的数量创建工作线程,本例当中,工作线程的数目和处理器数目是相同的 步骤四:创建监听套接字 步骤五,接入Socket,并和完成端口关联 步骤六 ...
windows TCP/IP 网络编程(七)5种windows网络模型(5)完成端口
vc的网络编程是和很通用的技术,其中,完成端口模式是最高效的
1. 今天软件工作室开发的23vs彩票分析软件号码服务端。 2. 使用VC++,完成端口多线程编程。 3. 编译环境VC2008
C#编程 网络安全及硬件控制 获得系统打开的端口和状态(源码)C#编程 网络安全及硬件控制 获得系统打开的端口和状态(源码)C#编程 网络安全及硬件控制 获得系统打开的端口和状态(源码)C#编程 网络安全及硬件控制 获得...
IOCP完成端口详解(pdf文档+源码) 包含有完成端口的详细介绍,以及在VC下成功应用完成端口的源代码,非常适合学习和掌握完成端口编程技术。 从网上下载的,放在CSDN上面,也给自己做一个备份。
1、在C#中,不用去面对完成端口的操作系统内核对象,Microsoft已经为我们提供了SocketAsyncEventArgs类,它封装了IOCP的使用。请参考:...
(6) 而此时,我们预先准备的那几个Worker线程就不能闲着了, 我们在前面建立的几个Worker就要忙活起来了,都需要分别调用GetQueuedCompletionStatus() 函数在扫描完成端口的队列里是否有网络通信的请求存在(例如...
学习完成端口编程很好的资料。IOCP完成端口编程
Windows_IO完成端口编程 Windows_IO完成端口编程
“完成端口”模型是迄今为止最为复杂的—种I/O模型。然而。假若—个应用程序同时需要管理为数众多的套接字,那么采用这种模型。往往可以达到最佳的系统性能。因其设计的复杂性,只有在你的应用程序需要同时管理数百...