当连接不到200个客户端时,WSASend出现错误.WSAENOBUFS,10055,为什么啊?利用setsockopt增加发送的缓存区也不行.请大家帮帮忙啊.

解决方案 »

  1.   

    The Windows Sockets provider reports a buffer deadlock
    WSAENOBUFS出错问题。
    这个问题并不直观,并且很难检查。因为,乍一看,它很像普通的死锁,或者内存泄露。假设你已经弄好了你的服务器并且能够很好的运行。当你对服务器进行承受力测试的时候,它突然挂机了。如果你幸运,你会发现这和WSAENOBUFS出错有关。
    伴随着每一次的重叠发送和接收操作,有数据的内存提交可能会被加锁。当内存被锁定时,它不能越过物理内存页。操作系统会强行为能够被锁定的内存的大小设定一个上限。当达到上限时,重叠操作将失败,并发送WSAENOBUFS错误。
    假如一个服务器在在每个连接上提供了很多重叠接收,随着连接数量的增长,很快就会达到这个极限。如果服务器能够预计到要处理相当多的并发客户端的话,服务器可以在每个连接上仅仅回复一个0字节的接收。这是因为没有接收操作和内存无关,内存不需要被锁定。利用这个方法,每一个套接字的接收内存都应该被完整的保留,这是因为,一旦0字节的接收操作完成,服务器仅仅为套接字的接收内存的所以数据内存返回一个非阻塞的接收。利用WSAEWOULDBLOCK,当非阻塞接收失败时,也没有数据被阻塞。这种设计的目的是,在牺牲数据吞吐量的情况下,能够处理最大量的并发连接。当然,对于客户端如何和服务器交互,你知道的越多越好。在以前的例子中,每当0字节的接收完成,返回存储了的数据,马上执行非阻塞接收。假如服务器知道客户端突然发送数据,当0字节接收一旦完成,为防止客户端发送一定数量的数据(大于每个套接字默认的8K内存大小),它可以投递一个或多个重叠接收。
      

  2.   

    你应该去看看这篇文章:
    http://www.codeproject.com/KB/IP/iocp_server_client.aspx他的工程实例中通过0 byte recv解决了这一问题,你可以下载源代码学习他的方法
      

  3.   

    这是一个办法
    但是会降低传输速度
    主要还是你发的比接受快了
    所以你可以发送的时候判断一下缓冲区时候已满再发
    得到缓冲区数据可以用DWORD dwTobeRead;
    if (ioctlsocket( sock, FIONREAD, &dwTobeRead ) != 0)
    goto error;
      

  4.   

    根据IOCP的说明来看,貌似可以提高速度的(不一定,特定情况下的)
      

  5.   


    WSAENOBUFS这是很严重的错误了,这是因为系统非分页内存池已经没有资源可用,系统随时都会崩溃或蓝屏的了,自己检查你的程序使用的非分页内存池不断增加,估计你是不是不停的WSASend(),令系统有N个还得于pending的WSASend(),锁定了N多非分页内存。
      

  6.   

    嗯.对啊.我一直不断的在WSASend(),那有什么解决办法吗?谢谢.
      

  7.   

    但返回WSA_IO_PENDING是正常的情况啊.