首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  网络/通讯  |  高性能网络服务器


完成端口及网络编程之QA(常见问题,持续添加)


原作者:sodme    源出处:CSDN    发布者:施昌权    发布类型:转载    发布日期:2009-02-23

      

   本文作者: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,但这个值是可以改的!

评论

#sodme 发表于2005-06-15 02:08:00  IP: 61.186.252.*
更新问题4:
4、为什么投递一个WSASend操作后,在Get函数中,获得发送完成事件的通知时,截获到的发送出去的数据却不是刚刚投递的数据?
原因:在投递WSASend时,会要求你指定数据缓冲区的地址,如果你此处的地址是通过new动态分配的,并且在投递过WSASend之后随之即delete了此空间,则可能会发生你的描述的这个现象。我的理解是:当WSASend操作还没有真正完成时,如果释放了数据缓冲区,那么WSASend将会因为缓冲区的释放而造成没有正确投递缓冲区内的数据,也就是说,WSASend在投递一个数据时,并没有即刻把数据拷到投递缓冲区去,如果是在WSASend完成后再释放此空间则不会发生这种情况。以上,只是偶的猜想,除调试结果外,到现在还没有获得其它信息加以证实。



关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号