select I/O模型用法

来源:互联网 发布:古屋敷由良知乎 编辑:程序博客网 时间:2024/05/20 18:44

  1、select 模型的原理是:分别将套接字往fd_read、fd_write、fd_error三个集合中进行填充,然后运用select方法阻塞调用。select方法就会去轮询网络协议栈,看是否有可读写的数据。如果有,就返回,就可以对数据进行读写。否则,在超时的时间就会返回。

 2、fd_read 填充条件

       2.1在有新的套接字连接请求、重连或关闭

       2.2有数据可读时

3、fd_write填充条件

   3.1有数据可写

   3.2非阻塞的套接字连接成功时。(常用于设置连接超时)

 

select模型简单服务器

代码如下:

 void CSelctSock::Run()
{
 while(TRUE)
 {
  if(WaitForSingleObject(m_hExit,10)== WAIT_OBJECT_0)
  {
   break;
  }

  sockaddr_in addr;
  int nLen = sizeof(sockaddr_in);
  g_FD_Read = g_FD_ALL;
  g_FD_Write = g_FD_Write;
  int nRet;
  
  //FD_READ的作用
  //1、有数据可读时
  //新连接、关闭连接或重启、断开(断开时可根据接收数据进行判断,len<=0时,表示断开)
  if((nRet=select(0,&g_FD_Read,&g_FD_Write,NULL,NULL))== SOCKET_ERROR)
  {
   cout << "select error\n";
  }
  else
  {
   for(int i=0; i< (int)g_FD_ALL.fd_count; i++)
   {
    if(FD_ISSET(g_FD_ALL.fd_array[i],&g_FD_Read))//fd_Read
    {
     if(g_FD_ALL.fd_array[i] == m_sockListen)//监听套接字接到新连接
     {
      SOCKET sock;
      sock = accept(m_sockListen,(sockaddr*)&addr,&nLen);
      FD_SET(sock,&g_FD_ALL);
      cout << "accept new socket" <<endl;
      char chrData[] = "to client data";
      send(sock,chrData,sizeof(chrData),0);
     }
     else
     {
      char chrData[1024];
      nLen = recv(g_FD_ALL.fd_array[i],chrData,1024,0);

      if(nLen > 0)//接收到数据
      {
       cout << "receive data :" << chrData << endl;
      }
      else//连接关闭、重启或中断
      {
       ::closesocket(g_FD_ALL.fd_array[i]);
       FD_CLR(g_FD_ALL.fd_array[i],&g_FD_ALL);
       cout << "the client is close" <<endl;
      }
     }
    }//end fd_read

    if(FD_ISSET(g_FD_ALL.fd_array[i],&g_FD_Write))
    {
     cout << "write fd" << endl;
    }
   }//end if

  }
 }


}

原创粉丝点击