现在在一个项目中要用到一个简单聊天室,就是没有所谓的服务器,每个客户端都要监听,我是简单的做了demo了是用WSAAsyncSelect做的,是不是用WSAAsyncSelect
比较会容易出现一些异常或者错误之类,由于我对网络编程不熟悉,没有经验不知道怎么捕捉和处理,大家给点经常会出现的异常,错误以及怎么处理,要是这个结构不好处理,是不是用阻塞,多线程比较好

解决方案 »

  1.   

    只要是你用的好哪个都好
    WSAAsyncSelect适合client
    我现在也用不好WSAAsyncSelect
      

  2.   

    WSAAsyncSelect并不是导致异常或错误的原因,主要是你的缓冲区管理(也就是主要是内存操作)没处理好,多线程情况下应该同步。
      

  3.   

    异常分C++异常和结构化异常。请看些C++的书和《Windows核心编程》
      

  4.   

    WSAAsyncSelect会自动把socket设置为非阻塞模式,至于出现的错误以及处理也没有特别的地方就是和其他非阻塞套接字一样,繁忙的时候会返回WSAEWOULDBLOCK错误,着重要处理好这个错误就好了WSAAsyncSelect模型作为服务器端,可以在系统开销不大的情况下同时处理很多连接,当然,如果连接不是特别多的话
      

  5.   

    WSAEWOULDBLOCK,这个错误是不是在send,recv,connect处发生,
    大家有没有比较成熟的例子,有处理这种错误的,拜托了
      

  6.   

    在非阻塞模式下执行I/O操作时,Winsock函数会返回并交出控制权。这种模式使用 起来比较复杂,因为函数在没有运行完成就进行返回,会不断地返回 WSAEWOULDBLOCK错误。
    为了解决这个问题,一般有:select,WSAAsyncSelect等模型来解决
      

  7.   

    我就是用WSAAsyncSelect模式的,但是还是不了解,
    send我是想把发送的数据放入一个自己开辟的buffer中,当数据发送成功时把buffer清空。要是,再次发送数据前判断是否buffer为空,为空就把新数据放入buffer,要是有WSAEWOULDBLOCK就等待FD_WRITE再次发送buffer中数据
    这个思路大家看一下有没有错误,或者那里还需要补充的
      

  8.   

    如果你是做的仅仅是聊天功能你说的足够了!
     如果你发的数据大,最好用如下结构:
    do
    {
       int Ret=send(....);
    }while(Ret==0);
    do
    {
      int Ret=recv(..)
    }while(Ret==0);
      

  9.   

    send 最好用如下结构:
     int nLeft=strlen(buffer);
     int nRet;
    while(nLeft)
    {
      nRet=send(...);
      nLeft -=nRet;  
    }
      

  10.   

    我大概是想这样做:
    int sendfun(SOCKET s,char * a,int len)
    {
         int ret = 0;
         int idx =0;
         while (len > 0)
         {
             ret = send(s,a+idx,len,0);
             if ( ret == SOCKET_ERROR)
             {
                 if ( WSAGetLastError() == 10035 )
                 {
                     break;//等待触发FD_WRITE,自动send发送位置从sendbuff+idx开始
                 } 
                 else
                 {
                    return idx;//自己再次send,发送位置从sendbuff+idx开始, sendfun(socket,sendbuf+idx,len);
                 }
             }
             len -= ret;
             idx += ret;
         }
         return 0;
    }
      

  11.   

    但是,在connect与recv该怎么处理我是没有一点头绪
      

  12.   

    呵,去http://www.vckbase.com/那几个网站看看了会有一点头绪的  :P
      

  13.   

    select 能不能与WSAAsyncSelect混合着用
      

  14.   

    要是connect时候出现WSAAsyncSelect要怎么处理,是不是其他就自己在connect
      

  15.   

    connect 这样写能不能行    if( connect(m_socket,(sockaddr*)(&m_connaddr),sizeof(m_connaddr)) == SOCKET_ERROR )
    {//判断出错原因
            ierr = WSAGetLastError();
            switch ( ierr )
    {
    case 10035:
    {
    while(bflag)
    {
         if ( connect(m_socket,(sockaddr*)(&m_connaddr),sizeof(m_connaddr)) == SOCKET_ERROR )
        {
                 if( WSAGetLastError() != 10035 )
    {
                 bflag = false;
    }          
    }
            else
    {
                 bflag = false;
    }
    }
    }
    break;
    default:
    {
    s.Format ("connect-errorcode-%d",WSAGetLastError());
    m_msglist.InsertString (0,s);
    closesocket(m_socket);
    m_socket = INVALID_SOCKET;
    }
    break;

    }
    }
      

  16.   

    在一个socket上注册了FD_WRITE,FD_READ,FD_CLOSE,几个事件,要是同时这几个事件触发,是不是会出错,
    是不是用这个来检测WSAGETSELECTERROR(lParam)
      

  17.   

    1. select 能不能与WSAAsyncSelect混合着用??    可以的,我们经常使用select来设置socket超时,另外send和recv超时设置的代码,如果需要我再贴到这里2.是不是用这个来检测WSAGETSELECTERROR(lParam)??
      
         是的,我们最好在确实事件的前面加上WSAGETSELECTERROR宏来判断套接字上是否发生了错误
    3.recv一般不会出现10035错误,直接响应FD_READ来接收就好了,connect出现的的几率也很小,你这样的处理方式是可行的。
      关键还是要把send的这个错误处理好,我大概看了一下,你的处理方式不错,基本上就是这样,就是响应FD_WRITE消息得到socket重新可写的通知,然后发送剩余的数据
      

  18.   

    检测WSAGETSELECTERROR(lParam)??检测到错误是不是直接关闭closesocket()
      

  19.   

    是的if(WSAGETSELECTERROR(lParam))
    {
       closesocket((SOCKET)wParam);
       break;
    }
      

  20.   

    http://www.vczx.com/article/show.php?id=654
      

  21.   

    结贴了,感谢兄弟们的支持,特别感谢 PiggyXP兄
      

  22.   

    噢,超时控制的代码是这样的//set Recv and Send time out
    int TimeOut=6000; //设置发送超时6秒
    if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
    return 0;
    }
    TimeOut=6000;//设置接收超时6秒
    if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
    return 0;
    }