Select模型的 单服务器多客户端示范代码

#include <stdio.h>
#include <iostream>
#include <winsock2.h>
using namespace std;
int main(){
    WORD version = MAKEWORD(2,2);
    WSADATA wsaData;
    SOCKET listenSocket;
    SOCKET acceptSocket;
    SOCKET clientSocket[FD_SETSIZE];
    int static index = 0;
    DWORD block = 1L;
    FD_SET ReadSet;
   //加载SOCKET库

    int f = WSAStartup(version,&wsaData);
    if (f != 0){
        cout<<"加载Winsock 库错误! 错误号:"<<WSAGetLastError()<<endl;
        return -1;

    }

    //创建监听SOCKET

    listenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
    if (listenSocket == INVALID_SOCKET){
        WSACleanup();
        cout<<"创建监听SOCKET失败! 错误号:"<<WSAGetLastError()<<endl;
        return -1;

    }
    cout<<"监听SOCKET创建成功!\n"<<endl;

    //构造服务器地址

    SOCKADDR_IN serverIp;

                serverIp.sin_family = AF_INET;
                serverIp.sin_port = htons(8108);
                serverIp.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    if (bind(listenSocket,(SOCKADDR*)&serverIp,sizeof(SOCKADDR)) == SOCKET_ERROR){
        cout<<"绑定服务器错误! 错误号:"<<WSAGetLastError()<<endl;
        return -1;

    }

    cout<<"绑定操作成功!\n"<<endl;
    if (listen(listenSocket,10) == SOCKET_ERROR){
        cout<<"进入监听模式错误! 错误号:"<<WSAGetLastError()<<endl;
        return -1;
    }
    cout<<"服务器已进入监听模式!\n"<<endl;

    if (ioctlsocket(listenSocket,FIONBIO,&block) == SOCKET_ERROR){
Cout<<"监听SOCKET设置为非阻塞模式错误! 错误号:"<<WSAGetLastError()<<endl;

        return -1;

    }

    cout<<"监听SOCKET已设置为非阻塞模式!\n\n\n"<<endl;


    //非阻塞模式接受客户端连接

    while(TRUE){

          cout<<"持续按非阻塞模式接受客户端连接请求!\n\n"<<endl;
          //将读SET 清0

          FD_ZERO(&ReadSet);

          //将已有客户端连接放到集合中!

          for (int i = 0; i < index; i  ){

        cout<<"将clientSocket["<<i<<"]放到ReadSet集合中!\n"<<endl;

               FD_SET(clientSocket[i],&ReadSet);
          }
        cout<<"监听SOCKET 放入 ReadSet集合中!\n\n"<<endl;

          FD_SET(listenSocket,&ReadSet);
          if (select(0,&ReadSet,NULL,NULL,NULL) == SOCKET_ERROR

              cout<<"select 监听SOCET错误! 错误号:"<<WSAGetLastError()<<endl;
              system("pause");
              return -1;
          }

          cout<<"select 返回 说明已有客户端进行连接或有客户端数据读取或有客户端连接断开!\n\n\n"<<endl;

              if (FD_ISSET(listenSocket,&ReadSet)){

                  cout<<"当前ReadSet中存监听SOCKET!\n\n"<<endl;
                  acceptSocket = accept(listenSocket,NULL,NULL);
                  if (acceptSocket != INVALID_SOCKET){
             cout<<"客户端建立连接成功并保存到clientSocket["<<index<<"]中!\n\n"<<endl;
                      clientSocket[index] = acceptSocket;
                      index++   ;

                  }else {
                      cout<<"接收客户端连接错误! 错误号:"<<WSAGetLastError()<<endl;

                   continue;

                  }
              }

              for (int j = 0; j < index; j  ){

                  if (FD_ISSET(clientSocket[j],&ReadSet)){
                      cout<<"当前ReadSet集合中有客户端SOCKET clientSocket["<<j<<"]可读数据!\n [message]"

                      char buffer[100]; memset(buffer,0,100);

                      if (recv(clientSocket[j],buffer,100,0) != SOCKET_ERROR){

                          cout<<buffer<<"[/messsage]\n"<<endl;

                      }else {

                          cout<<"客户端clientSocket["<<j<<"]出现错误! 错误号:"<<WSAGetLastError()<<endl;
                          clientSocket[j] = NULL;

                          index --;
                          closesocket(clientSocket[j])
                          break;

                      }


 }            }
    }
  }

下面这段代码与上面所述的While(True)部分基本一致,但我本人感觉下面的方法更好.

while(true)
 {

  fd_set fdRead=fdSocket;
  if (::select(0,&fdSocket,NULL,NULL,NULL)==SOCKET_ERROR)
  {
   continue;
  }
  else
  { 
  TRACE("Wait somebody % i\n ",fdSocket.fd_count);
  for(int i=0;i<(int)fdSocket.fd_count;i++)
  { 

   if(FD_ISSET( fdSocket.fd_array[i], &fdSocket))
   {
    if(fdSocket.fd_array[i]==sListen)   
    { 
     CString strIP;
     sockaddr_in addrRemote;
     int nAddrLen=sizeof(addrRemote);
     SOCKET sNew=::accept(sListen,(sockaddr*)&addrRemote,&nAddrLen);
     FD_SET(sNew,&fdSocket);
     strIP.Format( "%s",inet_ntoa(addrRemote.sin_addr) );
     TRACE("NEW COME    %s\n",strIP);

    }//end if ==slisten
    else
    {
     int nRecev=::recv(fdSocket.fd_array[i],(char*)&recvPacket,sizeof(recvPacket),0);
     if (nRecev>0)
     {
      TRACE("recv msg %s\n",recvPacket);

     }else
     {
      ::closesocket(fdSocket.fd_array[i]);
      FD_CLR(fdSocket.fd_array[i],&fdSocket);
     }
    }
   }
  
  }
  }
 }
  return 0;

原文地址:https://www.cnblogs.com/rainbowzc/p/1520113.html