Windows平台下基于Select模型的服务器

//   基于   select   模型的 socket   编程
#include   "stdafx.h"
#include   <winsock2.h>
#include   <iostream>
#pragma   comment (   lib ,   "ws2_32.lib"   )


using   namespace   std ;

enum
{
        MAIN_RETURN_ERROR            =  -1,
      MAIN_RETURN_NORMAL           =   0,
};


BOOL   CreateSocketInformation (   SOCKET   s   );
void   FreeSocketInfomation (   DWORD   Index   );


// WSABUF   WinSock2    中定义的   结构体,用于保存缓冲区的长度和地址
// struct _WSABUF
// {
//   u_long    len;   //   缓冲区的长度
//   char FAR* buf;   //   缓冲区的指针
// };

const   static   int   DATA_BUF_SIZE   = 256;
struct   _SOCKET_INFOMATION
{
        char       Buffer   [ DATA_BUF_SIZE ];       //   发送和接收数据缓冲区
        WSABUF     DataBuf   ;                     //   定义发送和接收数据缓冲区,保护缓冲区在内的长度和内容
        SOCKET     Socket   ;                      //   与客户端进行通信的   socket

        DWORD      BytesSEND   ;                   //   保存 socket   发送字节数
        DWORD      BytesRECV   ;                   //   保存 socket   接收字节数
};

typedef   _SOCKET_INFOMATION      SOCKET_INFOMATION ;
typedef   _SOCKET_INFOMATION   LPSOCKET_INFOMATION ;

const   static   int   BUF_SIZE   = 256;

DWORD   TotalSockets   = 0;
LPSOCKET_INFOMATION   SocketArray [   FD_SETSIZE ];



int   _tmain (   int   argc   ,   _TCHAR *   argv [])
{
        //   初始化 Winsock 2.2
        WSADATA   wsaData   ;
        if (   WSAStartup   (   MAKEWORD ( 2, 2 ), &   wsaData   ) != 0 )
     {
             cout << "WSAStartup   无法初始化   !"   << endl   ;
             return   MAIN_RETURN_ERROR   ;
     }

        //   通过 WinSock   实现网络通信
        SOCKET   AcceptSocket   ;
        SOCKET   ListenSocket   ;
      //   创建用于监听的 Socket
        ListenSocket   =   WSASocket   (   AF_INET ,   SOCK_STREAM , 0,   NULL , 0,   WSA_FLAG_OVERLAPPED   );
        if (   INVALID_SOCKET   ==   ListenSocket   )
     {
             cout << "Socket Failed !"   << " Reson:" <<   WSAGetLastError ()<< endl   ;
             WSACleanup ();
             return   MAIN_RETURN_ERROR   ;
     }

        //   设置服务器 Socket   地址
        SOCKADDR_IN   addrServ   ;
        addrServ . sin_family     =   AF_INET ;
        addrServ . sin_port       =   htons ( 9990 );     //   服务器端口号
        addrServ . sin_addr   . S_un .   S_addr   =   htonl   (   INADDR_ANY   );

        //   绑定
        int       retVal   ;
        retVal   =   bind   (   ListenSocket , (   const   struct   sockaddr   *)& addrServ   ,   sizeof (   SOCKADDR_IN   ) );
        if (   SOCKET_ERROR   ==   retVal   )
     {
             cout << "bind failed !"   << "   Reson: " <<   WSAGetLastError ()<< endl   ;
             closesocket (   ListenSocket   );
             WSACleanup ();
             return   -1;
     }

        //   监听
        retVal   =   listen   (   ListenSocket , 5 );
        if (   SOCKET_ERROR   ==   retVal   )
     {
             cout << "listen failed !"   << " Reson:" <<   WSAGetLastError ()<< endl   ;
             closesocket (   ListenSocket   );
             WSACleanup ();
             return   -1;
     }

        //   设置 socket   其为非阻塞模式   , argp   设为非零值
        int   iModel   = 1; 
        retVal   =   ioctlsocket   (   ListenSocket ,   FIONBIO , ( u_long   FAR * )& iModel   );
        if (   SOCKET_ERROR   ==   retVal   )
     {
             cout << "ioctlsocket failed  Reson :" <<   WSAGetLastError ()<< endl   ;
             WSACleanup ();
             return   MAIN_RETURN_ERROR   ;
     }

        //
        CreateSocketInformation   (   ListenSocket   );

        cout << "TCP Server Start ... ..."   << endl ;
        //   循环等待
        FD_SET   WriteSet   ;
        FD_SET   ReadSet   ;
        DWORD     Total   = 0;
        DWORD     SendBytes   ,   RecvBytes ;
        while (   true   )
     {
             FD_ZERO ( & ReadSet   );
             FD_ZERO ( & WriteSet   );
             FD_SET (   ListenSocket   , & ReadSet   );
             for (   DWORD   i   = 0;   i   <   TotalSockets   ; ++ i   )
          {
                 LPSOCKET_INFOMATION   SocketInfo   =   SocketArray   [ i ];
                 FD_SET (   SocketInfo   -> Socket , &   WriteSet   );
                 FD_SET (   SocketInfo   -> Socket , &   ReadSet   );
          }

             if ( (   Total   =   select ( 0, &   ReadSet , & WriteSet   ,   NULL ,   NULL   ) ) ==   SOCKET_ERROR   )
          {
                 cout << "Select Return with Error " <<   WSAGetLastError ()<< endl   ;
                 return   -1;
          }
          
             for (   DWORD   i   = 0;   i   <   TotalSockets   ; ++ i   )
          {
                 // SocketInfo   为当前要处理的信息
                 LPSOCKET_INFOMATION   SocketInfo   =   SocketArray   [ i ];
                 //   判断当前 socket   的可读性,即是否有接入的连接请求可以接收数据
                 if (   FD_ISSET   (   SocketInfo ->   Socket , & ReadSet   ) )
              {
                      //   对于监听来说,可读表示有新的连接请求
                      if (   SocketInfo   -> Socket   ==   ListenSocket   )
                   {
                           Total --;
                           //   接受连接请求,与客户端进行通信
                           if ( (   AcceptSocket   =   accept (   ListenSocket   ,   NULL ,   NULL   ) ) !=   INVALID_SOCKET   )
                        {
                                int   NonBlock   = 1;
                                if (   ioctlsocket   (   AcceptSocket   ,   FIONBIO , (   u_long   FAR   * )& NonBlock ) ==   SOCKET_ERROR   )
                             {
                                     cout << "ioctlsocket() failed with error " <<   WSAGetLastError ()<< endl   ;
                                     return   -1;
                             }

                                if (   CreateSocketInformation   (   AcceptSocket   ) ==   FALSE   )
                                     return   -1;
                        }
                           else
                        {
                                if (   WSAGetLastError   () !=   WSAEWOULDBLOCK   )
                             {
                                     cout << "accept failed with error " <<   WSAGetLastError ()<< endl   ;
                                     return   -1;
                             }
                        }
                   }
                      //   有新的数据到达
                      else
                   {
                           //   如果当前在 ReadSet 集合中,表明有数据可读
                           if (   FD_ISSET   (   SocketInfo ->   Socket , & ReadSet   ) )
                        {
                             --   Total ;
                                memset (   SocketInfo   -> Buffer ,   ' ' ,   DATA_BUF_SIZE   );
                                SocketInfo -> DataBuf   . buf   =   SocketInfo   -> Buffer ;
                                SocketInfo -> DataBuf   . len   =   DATA_BUF_SIZE   ;

                                //   接收数据
                                DWORD   Flags   = 0;
                                if (   WSARecv   (   SocketInfo   -> Socket , &(   SocketInfo -> DataBuf   ), 1, & RecvBytes   , & Flags ,   NULL ,   NULL   ) ==   SOCKET_ERROR   )
                             {
                                     if (   WSAEWOULDBLOCK   !=   WSAGetLastError   () )
                                  {
                                         cout << "WSARecv failed with error " <<   WSAGetLastError ()<< endl   ;
                                          FreeSocketInfomation   (   i   );
                                  }

                                     continue ;
                             }
                                else
                             {
                                     SocketInfo -> BytesRECV   =   RecvBytes   ;
                                     if (   RecvBytes   == 0 )
                                  {
                                          FreeSocketInfomation   (   i   );
                                         continue ;
                                  }
                                     else
                                  {
                                          cout << SocketInfo   -> DataBuf .   buf << endl   ;
                                  }
                             }
                        }
                   }
              }
                 else
              {
                      //   发送数据
                      if (   FD_ISSET   (   SocketInfo ->   Socket , & WriteSet   ) )
                   {
                        --   Total ;
                           SocketInfo -> DataBuf   . buf   =   SocketInfo   -> Buffer   +   SocketInfo -> BytesSEND   ;
                           SocketInfo -> DataBuf   . len   =   SocketInfo   -> BytesRECV   -   SocketInfo -> BytesSEND   ;
                           if (   SocketInfo   -> DataBuf .   len   > 0 )
                        {
                                if   WSASend   (   SocketInfo   -> Socket , &(   SocketInfo -> DataBuf   ), 1, & SendBytes   , 0,   NULL ,   NULL   ) ==   SOCKET_ERROR   )
                             {
                                     if (   WSAGetLastError   () !=   WSAEWOULDBLOCK   )
                                  {
                                         cout << "WSASend failed with error " <<   WSAGetLastError ()<< endl   ;
                                          FreeSocketInfomation   (   i   );
                                  }

                                     continue ;
                             }
                                else
                             {
                                     SocketInfo -> BytesSEND   +=   SendBytes   ;
                                     if (   SocketInfo   -> BytesSEND   ==   SocketInfo -> BytesRECV   )
                                  {
                                          SocketInfo -> BytesRECV   = 0;
                                          SocketInfo -> BytesSEND   = 0;
                                  }
                             }
                        }
                   }
              }
          }
     }
          
        //   最后做一些清理工作
        closesocket (   ListenSocket   );
        closesocket (   AcceptSocket   );
        WSACleanup ();
        system ( "pause"   );
        return   MAIN_RETURN_NORMAL   ;
}



//   创建   SOCKET
BOOL   CreateSocketInformation (   SOCKET   s   )
{
        LPSOCKET_INFOMATION   SI   ;
        //   SI   分配空间
        if ( (   SI   = ( LPSOCKET_INFOMATION )   GlobalAlloc (   GPTR   ,   sizeof   (   SOCKET_INFOMATION   ) ) ) ==   NULL   )
     {
             cout << "GlobalAlloc Failed with Error " <<   GetLastError ();
             return   FALSE   ;
     }

        SI -> Socket          =   s ;
        SI -> BytesSEND       = 0;
        SI -> BytesRECV       = 0;

        SocketArray [ TotalSockets   ] =   SI ;
     ++   TotalSockets ;

        return   TRUE   ;
}

void   FreeSocketInfomation (   DWORD   Index   )
{
        LPSOCKET_INFOMATION   SI   =   SocketArray [   Index ];
        DWORD   i   ;
        closesocket (   SI   -> Socket   );
        GlobalFree (   SI   );
        for (   i   =   Index ;   i   <   TotalSockets   ; ++ i   )
             SocketArray [ i   ] =   SocketArray [   i +1];

     --   TotalSockets ;
}



客户端1:


客户端2




服务器:

没有实现收到 服务端把数据发回客户端。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值