windows下socket编程的select使用

本文介绍在Windows环境下如何使用Socket编程,并详细讲解了Select函数的应用及注意事项。通过示例代码展示了如何设置非阻塞模式,绑定地址,监听连接请求等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

windows下socket编程的select使用

(2010-06-21 14:22:08)
标签:

socket

select

杂谈

分类: c++

2010年6月21日14:22:51

在window下socket编程

使用select的时候与linux下有些不同:

 

=============转载一段先=======================

1.select模型

int select(int nfds, // 忽略,为了与Berkeley兼容
fd_set FAR* readfds, // 1.1
fd_set FAR* writefds, // 1.2
fd_set FAR* exceptfds, // 1.3
const struct timeval FAR* timeout); // 1.4

1.1 readfds集合包括符合下述任何一个条件的套接字:
#有数据可以读入
#连接已经关闭,重设或终止
#加入已调用了listen,而且一个连接正在建立,那么accept函数调用会成功

1.2 writefdss集合包括符合下述任何一个条件的套接字:
#有数据可以发出
#如果已完成了对一个非锁定连接调用的处理,连接就会成功

1.3 exceptfdss集合包括符合下述任何一个条件的套接字:
#假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败.
#有带外(Out-of-band, OOB)数据可用读取

** 这三个参数中任意两个可以为空,但不能都为空,否则select没有等待任何数据.

1.4 struct timeval
struct timeval
{
long tv_sec; // (单位:秒)
long tv_usec; // (单位:毫秒)
}

** select()函数返回设置的监听socket发生操作,返回操作个数
e.g. int ret = select(0, &fdread, NULL, NULL, &tv);
当监视的socket发生读操作时,ret返回列队中的个数,于是产生后续的操作

** 个人绝对select就是为了accept函数能够立即返回,不会造成系统卡在一个函数上,导致挂起的样子,但是cpu使用率会飙升,那还不如就直接用accept,至少cpu占用率不会飙升(在没有连接到来的时候)

===========================

fd中保存的socket是不能直接使用的,必须额外设置一个数组保存socket,在每次select完之后,需要重新将数组中的socket FD_SET到fd中(我不清楚为什么,反正如果不这样的话select会出问题)。

 

 附上自己写的一段代码

=================

int initWinSock()
{
    WSADATA wsaData;
    WORD wVersionRequested=MAKEWORD(1,1);
    if( 0 == WSAStartup (wVersionRequested, &wsaData))
    {
        cout<<"RUN-MSG:Sucess to connect to the lib of socket!"<<endl;
        return 0;
    }
    else
    {
        cout<<"ERR-MSG:Failed to connect to the lib of socket!"<<endl;
        return -1;
    }
    //wVersionRequested是我们要求使用的WinSock的版本。
}

void* ServerThread(void* para)
    
}

int main(int argc, char *argv[])
{
#ifdef _WIN32
    cout<<"win32!"<<endl;
    if(0 != initWinSock())
         return -1;
#else
    cout<<"Linux!"<<endl;
#endif
    int sock, client_sock;
    int sock_arr[64];
 static int s_num_socket = 0;
    short sport = 8989;
    string sip  = "127.0.0.1";
   
    if(argc == 2)
        sport = atoi(argv[1]);
    if(argc == 3)
    {
        sport = atoi(argv[1]);
        sip   = argv[2];
    }
    cout<<"ip is "<<sip<<", port is "<<sport<<endl;
   
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in sockaddr, client_addr;
    fd_set fd, newfd;
    int error_code;
    int len ,l;
    string strread = "";
          
   // sockaddr.sin_family      = AF_INET;
  //  sockaddr.sin_port        = htons(sport);
   // sockaddr.sin_addr.s_addr = inet_addr(INADDR_ANY);
   
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("127.0.0.1");//0;//;//inet_addr(INADDR_ANY);
    sockaddr.sin_port = htons(sport);
   
 if((SOCKET_ERROR == bind(sock,(struct sockaddr *)&sockaddr, sizeof(struct sockaddr_in))) )
 {
        cout<<"ERR-MSG:bind error! :"<<error_code<<endl;
        cout<<WSAGetLastError()<<endl;
        system("PAUSE");
     return -2;
 }
 else
        cout<<"RUN-MSG:bind sucess!"<<endl;
 
 
 if(SOCKET_ERROR == (error_code = listen(sock, 20)) )
 {
        cout<<"ERR-MSG:listen error! :"<<error_code<<endl;
        system("PAUSE");
  return -3;
 }
 else
     cout<<"RUN-MSG:listen success!the port is:"<<sport<<endl;
    
    u_long mode = 1;
    ioctlsocket(sock,FIONBIO,&mode);
   // ioctlsocket(sock, FIONBIO,(u_long FAR*) &mode);//设置非阻塞的socket
    char opt = 1; 
   // setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
    FD_ZERO(&fd);
    FD_SET(sock, &fd);
    sock_arr[s_num_socket++] = sock;
    char buffer[256];
    memset(buffer, 0, 256);
    len = sizeof(struct sockaddr_in);
    int i;
    newfd = fd;
    while(1)
    {
     
           int ret = select(0, &newfd, NULL, NULL, NULL);
           if(ret < 0)
           {
               cout<<"ERR-MSG:select error!"<<endl;
               system("PAUSE");
               return -1;
           }
           for(i=0; i<s_num_socket; i++)
           {
     
      if(FD_ISSET(sock_arr[i], &newfd))
      {
       cout<<"i is"<<i<<endl;
       if(sock_arr[i] == sock)
       {
      cout<<"RUN-MSG:it's me!"<<endl;
      if((client_sock = accept(sock, (struct sockaddr*)&client_addr ,&len)) != INVALID_SOCKET)
      {
       cout<<"RUM-MSG:a new client!"<<endl;
       FD_SET(client_sock, &newfd);
       sock_arr[s_num_socket++] = client_sock;
       memset(buffer, 0, 256);
            
       }
       else
       {
        int ret = recv(sock_arr[i], buffer, 256, 0);
        if(ret > 1)
               cout<<buffer<<endl;
                       else
                       {
         if (WSAGetLastError() == WSAECONNRESET)
         {
          // Client socket closed
          cout<<"RUN-MSG:Client socket "<<sock_arr[i]<<"has close"<<endl;
          if(sock_arr[i] != INVALID_SOCKET)
          {
         FD_CLR(sock_arr[i], &newfd);
         close(sock_arr[i]);
          }
        cout<<"RUN-MSG:Remove client socket!"<<sock_arr[i]<<" success!"<<endl;
        sock_arr[i--] = sock_arr[--s_num_socket];
       } //坏连接
        }//坏连接的情况
       }
      }
     
           }
     FD_ZERO(&newfd);
     //重新置newfd状态;
     for(i=0; i<s_num_socket; i++)
    FD_SET(sock_arr[i],&newfd);
     sleep(1);
          
       
    close_sock(sock);
    WSACleanup();
    system("PAUSE");
    return EXIT_SUCCESS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值