int BaseSocket::mytcpsend(const char *str,int len)
{
     sendlen = send(mysocket,str,len,SEND_FLAG);
     if(sendlen == -1 || sendlen > len)
     {
showSktError();
return -1;
     }
     return 0;
}这是很简单的发送数据的方法,众所周知,在异步模式下发送数据太快就会出现WSAEWOULDBLOCK错误。我知道在MFC下响应FD_WRITE就行,但现在这是一个单纯的c++命令行程序,而且是在UNIX下用的,所以没有MFC,没有窗口,没有消息机制, 应该怎么办呀?

解决方案 »

  1.   

    不要使用消息,用事件WSAEventSelect()
      

  2.   

    用延时并不是个好做法啊。WSAEventSelect()怎么用在着啊
      

  3.   

    使用异步当然要返回WSAEWOULDBLOCK了,因为端口操作没有完成,这不是错误
      

  4.   

    WSAEventSelect模型
    WSAEventSelect模型类似WSAAsynSelect模型,但最主要的区别是网络事件发生时会被发
    送到一个事件对象句柄,而不是发送到一个窗口。使用步骤如下:
    a、 创建事件对象来接收网络事件:
    #define WSAEVENT HANDLE
    #define LPWSAEVENT LPHANDLE
    WSAEVENT WSACreateEvent( void );该函数的返回值为一个事件对象句柄,它具有两种工作状态:已传信(signaled)和未传信
    (nonsignaled)以及两种工作模式:人工重设(manual reset)和自动重设(auto reset)。默认未
    未传信的工作状态和人工重设模式。b、将事件对象与套接字关联,同时注册事件,使事件对象的工作状态从未传信转变未
    已传信。
          int  WSAEventSelect( SOCKET s,WSAEVENT hEventObject,long lNetworkEvents );  
    s为套接字
    hEventObject为刚才创建的事件对象句柄
    lNetworkEvents为掩码,定义如上面所述c、I/O处理后,设置事件对象为未传信BOOL WSAResetEvent( WSAEVENT hEvent );
    Hevent为事件对象成功返回TRUE,失败返回FALSE。d、等待网络事件来触发事件句柄的工作状态:DWORD WSAWaitForMultipleEvents( DWORD cEvents,
    const WSAEVENT FAR * lphEvents, BOOL fWaitAll,
    DWORD dwTimeout, BOOL fAlertable );
    lpEvent为事件句柄数组的指针
    cEvent为为事件句柄的数目,其最大值为WSA_MAXIMUM_WAIT_EVENTS 
    fWaitAll指定等待类型:TRUE:当lphEvent数组重所有事件对象同时有信号时返回;
    FALSE:任一事件有信号就返回。
    dwTimeout为等待超时(毫秒)
    fAlertable为指定函数返回时是否执行完成例程对事件数组中的事件进行引用时,应该用WSAWaitForMultipleEvents的返回值,减去
    预声明值WSA_WAIT_EVENT_0,得到具体的引用值。例如:nIndex=WSAWaitForMultipleEvents(…);
    MyEvent=EventArray[Index- WSA_WAIT_EVENT_0];
    e、判断网络事件类型:int WSAEnumNetworkEvents( SOCKET s,
    WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents );
    s为套接字
    hEventObject为需要重设的事件对象
    lpNetworkEvents为记录网络事件和错误代码,其结构定义如下:typedef struct _WSANETWORKEVENTS {
    long lNetworkEvents;
    int iErrorCode[FD_MAX_EVENTS];
    } WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
    f、关闭事件对象句柄:BOOL WSACloseEvent(WSAEVENT hEvent);
    调用成功返回TRUE,否则返回FALSE。
      

  5.   

    在unix中。如果是linux,那就用epoll来做,出现这个消息,并不是 错误,你再尝试就是了FreeBSD用kevent也可以实现aio的一个方法。
      

  6.   

    unix 怎么返回的WSAEWOULDBLOCK?
      

  7.   

    用宏定义区分了在UNIX下和在Windows下的不同啊,我在windows下调试,所以出WSAEWOULDBLOCK了。谢谢大家了。我用这种方法测了一下,发现socket连续不停的出WSAEWOULDBLOCK,始终在循环里出不来了,
    do{
      Sleep(20);
      sendlen = send(mysocket,str,len,SEND_FLAG);
    }
    while(sendlen == -1 && WSAGetLastError() == WSAEWOULDBLOCK)所以我怀疑是socket发生了类似死锁一样的情况,始终无法去做写操作了,这有可能是什么原因造成的啊?会不会是一个socket上同时发生读和写操作啊?
      

  8.   

    返回这个错误主要是因为资源暂时不可用。
    Resource temporarily unavailable. 
    This error is returned from operations on non-blocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a non-fatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a non-blocking SOCK_STREAM socket, since some time must elapse for the connection to be established. 
      

  9.   

    是资源暂时不可用,但原因是什么,有什么解决方法。通常资源暂时不可用,只要Sleep一会,资源就可用了,但现在就是不论Sleep多久,资源始终都不可用。同样得,我又做了一些测试,用select检测这个socket,发现这个socket工作一会后出现WSAEWOULDBLOCK后,就会一直处在不可写的状态了,也就是资源始终不能用了。