<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《windows網絡編程技術》之 Winsock I/O方法(1)

      select模型:

      select函數原型

      int select(

          int nfds,

          fd_set   FAR * readfds,

          fd_set   FAR * writefds,

          fd_set   FAR * exceptfds,

          const struct  timeval  FAR * timeout

      );

      nfds為了保持與早期兼容,可忽略。

      fd_set,代表一系列特定的套接字的集合,readset用于檢查可讀性,writeset用于檢查可寫性,exceptset用于檢查異常數據,具體用法如下:

      假定我們想測試一個套接字是否可讀,必須將該套接字增加到readset中,再等待select函數完成,完成后判斷該套接字是否仍然是readset集合的一部分,是,則該套接字可讀。三個參數至少有一個不為null。

      其中的timeval的結構如下:

      struct timeval

      {

         long      tv_sec;  (秒)

         long      tv_usec; (毫秒)

      }

       

      如select函數調用失敗,返回SOCKET_ERROR.

      對fd_set集合進行操作,可用宏:

      FD_CLR(s,*set):從set中刪除套接字s;

      FD_ISSET(s,*set):檢查s是否是set集合的一員,返回true或false

      FD_SET(s,*set):將套接字s加入集合set

      FD_ZERO(*set):將set初始化為空集合。

       


      WSAAsyncSelect 模型  

      利用這個模型,應用程序可在一個套接字上接收以Windows消息為基礎的網絡時間通知。使用這種模型,必須提供一個“窗口”,用于接收消息。函數原型如下:

      int WSAAsyncSelect(

              SOCKET   s,

              HWND    hwnd,

              unsigned   int  wMsg,

              Long   lEvent

      );

      s:對應套接字

      hwnd:接收消息的窗體句柄

      wMsg:發送的消息,應該為一個比WM_USER大的值。

      IEvent:對應為一系列網絡事件的組合,包括:FD_READ,FD_WRITE,FD_ACCEPT,FD_CONNECT,FD_CLOSE.

      如:WSAAsyncSelect(s,hwnd,WM_SOCKET,FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE)

      在調用WSAAsyncSelect后,即在hwnd對應的窗體回調函數中對網絡事件(消息)進行處理:

      LRESULT CALLBACK WindowProc(

          HWND   hWnd,

          UINT     uMsg,

           WPARAM  wParam,

          LPARAM    lParam

      );

      其中wParam指定在其上面發生了一個網絡事件的套接字。

      lParam低字節指定了已經發生的網絡事件,而lParam的高字節包含了可能出現的錯誤代碼。在網絡事件消息到達的時候,先調用WSAGETSELECTERROR宏返回高字節包含的錯誤信息。若沒有錯誤,則調用WSAGETSELECTEVENT宏返回lParam低字節部分。

       

      WSAEventSelect 模型

      和WSAAsyncSelect模型不同的是,這種模型中網絡事件會投遞至一個事件對象句柄,而非窗口句柄。所以要求我們針對每一個套接字都要建立一個事件對象。用WSACreateEvent函數,定義如下:

      WSAEVENT   WSACreateEvent(void);

      然后調用WSAEventSelect函數,定義如下:

      int   WSAEventSelect(

              SOCKET  s;

              WSAEVENT    hEventObject,

              long    lNetworkEvents

      );

      鑒于這個模型的復雜性,還是用代碼說話吧:

      #include
      #include
      #include

      #define PORT 5150
      #define DATA_BUFSIZE 8192

      typedef struct _SOCKET_INFORMATION {
         CHAR Buffer[DATA_BUFSIZE];
         WSABUF DataBuf;
         SOCKET Socket;
         DWORD BytesSEND;
         DWORD BytesRECV;
      } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

      BOOL CreateSocketInformation(SOCKET s);
      void FreeSocketInformation(DWORD Event);

      DWORD EventTotal = 0;
      WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
      LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS];

      void main(void)
      {
         SOCKET Listen;
         SOCKET Accept;
         SOCKADDR_IN InternetAddr;
         DWORD Event;
         WSANETWORKEVENTS NetworkEvents;
         WSADATA wsaData;
         DWORD Ret;
         DWORD Flags;
         DWORD RecvBytes;
         DWORD SendBytes;

         if ((Ret = WSAStartup(0x0202, &wsaData)) != 0//初始化winsock
         {
            printf("WSAStartup() failed with error %d\n", Ret);
            return;
         }

         if ((Listen = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) //創建Listen套接字
         {
            printf("socket() failed with error %d\n", WSAGetLastError());
            return;
         }

         CreateSocketInformation(Listen);  //創建一個_SOCKET_INFORMATION結構實體

         if (WSAEventSelect(Listen, EventArray[EventTotal - 1], FD_ACCEPT|FD_CLOSE) == SOCKET_ERROR)
         {
            printf("WSAEventSelect() failed with error %d\n", WSAGetLastError());
            return;
         }

         InternetAddr.sin_family = AF_INET;
         InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
         InternetAddr.sin_port = htons(PORT);

         if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
         {
            printf("bind() failed with error %d\n", WSAGetLastError());
            return;
         }

         if (listen(Listen, 5))
         {
            printf("listen() failed with error %d\n", WSAGetLastError());
            return;
         }
             

         while(TRUE)
         {
            // Wait for one of the sockets to receive I/O notification and
            if ((Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,
               WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
            {
               printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
               return;
            }

      //通過SocketArray[Event - WSA_WAIT_EVENT_0]獲得事件是在哪個socket上發生

      //通過WSAEnumNetworkEvents獲得發生了什么類型的網絡事件
            if (WSAEnumNetworkEvents(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, EventArray[Event -
               WSA_WAIT_EVENT_0], &NetworkEvents) == SOCKET_ERROR)  //必須減去預定義值,才能得到實際的索引位置
            {
               printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
               return;
            }

           
            if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
            {
               if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
               {
                  printf("FD_ACCEPT failed with error %d\n", NetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
                  break;
               }

               if ((Accept = accept(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, NULL, NULL)) == INVALID_SOCKET)
               {  
                  printf("accept() failed with error %d\n", WSAGetLastError());
                  break;
               }

               if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS)
               {
                  printf("Too many connections - closing socket.\n");
                  closesocket(Accept);
                  break;
               }

               CreateSocketInformation(Accept);//一旦有套接字accepted了,就創建事件對象和LPSOCKET_INFORMATION 結構

               if (WSAEventSelect(Accept, EventArray[EventTotal - 1], FD_READ|FD_WRITE|FD_CLOSE) == SOCKET_ERROR) //繼續對accepted 的 套接字調用WSAEventSelect
               {
                  printf("WSAEventSelect() failed with error %d\n", WSAGetLastError());
                  return;
               }

               printf("Socket %d connected\n", Accept);
            }


            // Try to read and write data to and from the data buffer if read and write events occur.

            if (NetworkEvents.lNetworkEvents & FD_READ ||
               NetworkEvents.lNetworkEvents & FD_WRITE)
            {
               if (NetworkEvents.lNetworkEvents & FD_READ &&
                  NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
               {
                  printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]);
                  break;
               }

               if (NetworkEvents.lNetworkEvents & FD_WRITE &&
                  NetworkEvents.iErrorCode[FD_WRITE_BIT] != 0)
               {
                  printf("FD_WRITE failed with error %d\n", NetworkEvents.iErrorCode[FD_WRITE_BIT]);
                  break;
               }

               LPSOCKET_INFORMATION SocketInfo = SocketArray[Event - WSA_WAIT_EVENT_0];

               // Read data only if the receive buffer is empty.

               if (SocketInfo->BytesRECV == 0)
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer;
                  SocketInfo->DataBuf.len = DATA_BUFSIZE;

                  Flags = 0;
                  if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
                     &Flags, NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSARecv() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
                        return;
                     }
                  }
                  else
                  {
                     SocketInfo->BytesRECV = RecvBytes;
                  }
               }

               // Write buffer data if it is available.

               if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
                  SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

                  if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
                     NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSASend() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
                        return;
                     }

                     // A WSAEWOULDBLOCK error has occured. An FD_WRITE event will be posted
                     // when more buffer space becomes available
                  }
                  else
                  {
                     SocketInfo->BytesSEND += SendBytes;

                     if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
                     {
                        SocketInfo->BytesSEND = 0;
                        SocketInfo->BytesRECV = 0;
                     }
                  }
               }
            }

            if (NetworkEvents.lNetworkEvents & FD_CLOSE)
            {
               if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
               {
                  printf("FD_CLOSE failed with error %d\n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]);
                  break;
               }

               printf("Closing socket information %d\n", SocketArray[Event - WSA_WAIT_EVENT_0]->Socket);

               FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
            }
         }
         return;
      }


      BOOL CreateSocketInformation(SOCKET s)
      {
         LPSOCKET_INFORMATION SI;
           
         if ((EventArray[EventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT)
         {
            printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());
            return FALSE;
         }

         if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
            sizeof(SOCKET_INFORMATION))) == NULL)
         {
            printf("GlobalAlloc() failed with error %d\n", GetLastError());
            return FALSE;
         }

         // Prepare SocketInfo structure for use.

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

         SocketArray[EventTotal] = SI;

         EventTotal++;

         return(TRUE);
      }


      void FreeSocketInformation(DWORD Event)
      {
         LPSOCKET_INFORMATION SI = SocketArray[Event];
         DWORD i;

         closesocket(SI->Socket);

         GlobalFree(SI);

         WSACloseEvent(EventArray[Event]);

         // Squash the socket and event arrays

         for (i = Event; i < EventTotal; i++)
         {
            EventArray[i] = EventArray[i + 1];
            SocketArray[i] = SocketArray[i + 1];
         }

         EventTotal--;
      }

      有了源代碼,一切都是那么清晰,呵呵。

      終于可以進入重疊模型了。。。

       

      posted @ 2006-05-26 20:24  紅心李  閱讀(266)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久热这里只有精品视频3| 精品久久久中文字幕一区| 亚洲日本韩国欧美云霸高清| 国产乱妇无码大片在线观看| 国产中文三级全黄| 精品无码国产一区二区三区AV| 18禁在线一区二区三区| 免费的特黄特色大片| 亚洲午夜无码久久久久蜜臀av| 人妻少妇偷人精品视频| 成人资源网亚洲精品在线| 精品国产中文字幕av| 婷婷丁香五月深爱憿情网| 一区二区三区国产亚洲自拍| 中文字幕日韩精品亚洲一区| 国产AV福利第一精品| 91久久偷偷做嫩草影院免费看| 中文字幕av无码免费一区| 国产女人被狂躁到高潮小说| 国产精品激情| 国产欧美亚洲精品第一页在线| 日本韩无专砖码高清观看| 久久国产精品成人影院| 果冻传媒mv免费播放在线观看| 综合欧美视频一区二区三区| 男人的天堂av一二三区| 又粗又大又黄又硬又爽免费看| 亚洲乱人伦中文字幕无码| 亚洲高清WWW色好看美女| 亚洲av无码片在线播放| 视频二区中文字幕在线| 熟妇人妻系列aⅴ无码专区友真希| 亚洲国产成人无码av在线播放| 久久国产国内精品国语对白| 99e久热只有精品8在线直播| 亚洲中文久久久精品无码| 日韩av毛片福利国产福利| 精品一区二区中文字幕| 免费拍拍拍网站| 人妻少妇偷人精品免费看| 日韩精品视频一区二区不卡|