青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

kenlistian

厚積薄發(fā). 勤為槳,思為帆

   :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理 ::
  73 隨筆 :: 4 文章 :: 22 評論 :: 0 Trackbacks

來自微軟的完成端口例子,就講解一下它的使用套路吧
反正編程這個玩意,只要用過,自然就知道什么回事,一次不會再看一次,學(xué)習(xí)這個玩意,無他,勤奮而已。
奢談效率等等,那只是孰能生巧上的功夫。
 

  這個例子是在console下的例子,算是一個echo服務(wù)器吧,
  跑起來后將在5150端口監(jiān)聽,一旦有個端口連接上來,發(fā)個數(shù)據(jù)給服務(wù)端口,它就echo回數(shù)據(jù)給那個端口. 直到那個連接中斷.
 
 完成端口,其實理解成一個通道或管子就可以了,和管道也差不了多少,不過可以實現(xiàn)異步處理罷了,
 你這邊往管子里丟數(shù)據(jù),通過GetQueuedCompletionStatus來查管子那頭出數(shù)據(jù)沒,出了就處理,這個管子就是通過一個自定義有點特殊的結(jié)構(gòu)來寫入或讀出數(shù)據(jù)而已.
 那個完成端口,其實就相當是標識那個數(shù)據(jù)塊的句柄,

//下面請看例子
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#define PORT 5150
#define DATA_BUFSIZE 8192

#pragma comment(lib, "Ws2_32")

typedef struct                        //這個玩意就是灌數(shù)據(jù),取數(shù)據(jù)的一個自定義數(shù)據(jù)結(jié)構(gòu)

                                              //和那個wm_data差不了多少,不過就是老要塞一個OverLapped結(jié)構(gòu),
{
   OVERLAPPED Overlapped;
   WSABUF DataBuf;
   CHAR Buffer[DATA_BUFSIZE];                    
   DWORD BytesSEND;                                 //發(fā)送字節(jié)數(shù)
   DWORD BytesRECV;                                
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;


typedef struct
{
   SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;


DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);


void main(void)
{
   SOCKADDR_IN InternetAddr;
   SOCKET Listen;
   SOCKET Accept;
   HANDLE CompletionPort;
   SYSTEM_INFO SystemInfo;
   LPPER_HANDLE_DATA PerHandleData;
   LPPER_IO_OPERATION_DATA PerIoData;
   int i;
   DWORD RecvBytes;
   DWORD Flags;
   DWORD ThreadID;
   WSADATA wsaData;
   DWORD Ret;

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

   //
   //完成端口的建立得搞2次,這是第一次調(diào)用,至于為什么?我問問你
   //
   if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
   {
      printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError());
      return;
   }
   //老套子api,不談也罷
   GetSystemInfo(&SystemInfo);
  
   //發(fā)現(xiàn)2個CPU,那就開個雙倍的線程跑吧
   for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
   {
      HANDLE ThreadHandle;
     
      //
      //完成端口掛到線程上面來了,就像管子把灌數(shù)據(jù)的和讀數(shù)據(jù)的兩頭都連上了,           
     //
      if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,
         0, &ThreadID)) == NULL)
      {
         printf("CreateThread() failed with error %d\n", GetLastError());
         return;
      }     
      CloseHandle(ThreadHandle);
   }

   //
   //啟動一個監(jiān)聽socket ,以下都是長長的交代
   //
   if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
      WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
   {
      printf("WSASocket() 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) == SOCKET_ERROR)
   {
      printf("listen() failed with error %d\n", WSAGetLastError());
      return;
   }

   //
   // 監(jiān)聽端口打開,就開始在這里循環(huán),一有socket連上,WSAAccept就創(chuàng)建一個socket,
   // 這個socket 又和完成端口聯(lián)上,
   //
   // 嘿嘿,完成端口第二次調(diào)用那個createxxx函數(shù),為什么,留給人思考思考可能更深刻,
   // 反正這套路得來2次,
   // 完成端口completionport和accept socket掛起來了,
   //
   while(TRUE)
   {

    //主線程跑到這里就等啊等啊,但是線程卻開工了,
      if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
      {
         printf("WSAAccept() failed with error %d\n", WSAGetLastError());
         return;
      }
     
      if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
      {
         printf("GlobalAlloc() failed with error %d\n", GetLastError());
         return;
      }     
     
      PerHandleData->Socket = Accept;
     
      //
     //把這頭和完成端口completionPort連起來
     //就像你把漏斗接到管子口上,開始要灌數(shù)據(jù)了
     //
      if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
         0) == NULL)
      {
         printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
         return;
      }
     
      //
      //清管子的數(shù)據(jù)結(jié)構(gòu),準備往里面灌數(shù)據(jù)
      //
      if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
      {
         printf("GlobalAlloc() failed with error %d\n", GetLastError());
         return;
      }

      ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
      PerIoData->BytesSEND = 0;
      PerIoData->BytesRECV = 0;
      PerIoData->DataBuf.len = DATA_BUFSIZE;
      PerIoData->DataBuf.buf = PerIoData->Buffer;

      Flags = 0;
     
      //
      //  accept接到了數(shù)據(jù),就放到PerIoData中,而perIoData又通過線程中的函數(shù)取出,
     //
      if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
         &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
      {
         if (WSAGetLastError() != ERROR_IO_PENDING)
         {
            printf("WSARecv() failed with error %d\n", WSAGetLastError());
            return;
         }
      }
   }
}

//
//線程一但調(diào)用,就老在里面循環(huán),
// 注意,傳入的可是完成端口啊,就是靠它去取出管子中的數(shù)據(jù)
//
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
   HANDLE CompletionPort = (HANDLE) CompletionPortID;
  
   DWORD BytesTransferred;
   LPOVERLAPPED Overlapped;
   LPPER_HANDLE_DATA PerHandleData;
   LPPER_IO_OPERATION_DATA PerIoData;        
   DWORD SendBytes, RecvBytes;
   DWORD Flags;
 
   while(TRUE)
   {
      //
      //在這里檢查完成端口部分的數(shù)據(jù)buf區(qū),數(shù)據(jù)來了嗎?
      // 這個函數(shù)參數(shù)要看說明,
      // PerIoData 就是從管子流出來的數(shù)據(jù),
      //PerHandleData 也是從管子里取出的,是何時塞進來的,
     //就是在建立第2次createIocompletionPort時
    // 

      if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
         (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
      {
         printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
         return 0;
      }

      // 檢查數(shù)據(jù)傳送完了嗎
      if (BytesTransferred == 0)
      {
         printf("Closing socket %d\n", PerHandleData->Socket);

         if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
         {
            printf("closesocket() failed with error %d\n", WSAGetLastError());
            return 0;
         }

         GlobalFree(PerHandleData);
         GlobalFree(PerIoData);
         continue;
      }    
     //
    //看看管子里面有數(shù)據(jù)來了嗎?=0,那是剛收到數(shù)據(jù)
    //
      if (PerIoData->BytesRECV == 0)
      {
         PerIoData->BytesRECV = BytesTransferred;
         PerIoData->BytesSEND = 0;
      }
      else   //來了,
      {
         PerIoData->BytesSEND += BytesTransferred;
      }
  
      //
      // 數(shù)據(jù)沒發(fā)完?繼續(xù)send出去
     //
     if (PerIoData->BytesRECV > PerIoData->BytesSEND)
      {

         ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); //清0為發(fā)送準備
         PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
         PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;

       //1個字節(jié)一個字節(jié)發(fā)送發(fā)送數(shù)據(jù)出去
         if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0,
            &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
         {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
               printf("WSASend() failed with error %d\n", WSAGetLastError());
               return 0;
            }
         }
      }
      else
      {
         PerIoData->BytesRECV = 0;

         Flags = 0;
         ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));

         PerIoData->DataBuf.len = DATA_BUFSIZE;
         PerIoData->DataBuf.buf = PerIoData->Buffer;

         if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
            &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
         {
            if (WSAGetLastError() != ERROR_IO_PENDING)
            {
               printf("WSARecv() failed with error %d\n", WSAGetLastError());
               return 0;
            }
         }
      }
   }
}

posted on 2006-05-25 22:27 kenlistian 閱讀(2468) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日韩国产123区| 91久久精品一区二区三区| 黄网动漫久久久| 国产在线一区二区三区四区| 国产精品性做久久久久久| 国产欧美视频一区二区三区| 国产精品自在线| 在线看无码的免费网站| 亚洲高清一区二| 99pao成人国产永久免费视频| 夜夜嗨网站十八久久| 亚洲欧美999| 狂野欧美一区| 亚洲欧洲精品一区二区三区| 中文欧美日韩| 久久一二三四| 欧美午夜在线观看| 影音先锋中文字幕一区二区| 一区二区欧美精品| 久久人人超碰| 一区二区三区久久久| 久久爱www久久做| 欧美日韩国产另类不卡| 欧美怡红院视频| 欧美日本免费一区二区三区| 亚洲高清资源| 亚洲欧美国产制服动漫| 久久综合九色综合久99| 欧美日韩国产综合网| 国外成人性视频| 亚洲欧美国产另类| 亚洲国产精品激情在线观看| 亚洲欧美卡通另类91av| 欧美高清视频一区| 国产一区二区视频在线观看| 亚洲无毛电影| 亚洲国产一成人久久精品| 欧美在线播放视频| 国产精品色在线| 9色精品在线| 欧美成人乱码一区二区三区| 亚洲综合久久久久| 国产精品vvv| 亚洲午夜精品一区二区| 亚洲第一毛片| 久热国产精品| 在线视频观看日韩| 噜噜噜久久亚洲精品国产品小说| 亚洲综合色激情五月| 国产精品美腿一区在线看 | 欧美日韩一区二区三| 今天的高清视频免费播放成人 | 尤物在线观看一区| 久久久久国产精品一区三寸| 亚洲一区日韩| 国产精品一区二区三区久久| 亚洲自拍偷拍色片视频| 一本色道久久综合狠狠躁篇怎么玩 | 猛男gaygay欧美视频| 久久国产综合精品| 一区免费视频| 欧美成人精品h版在线观看| 久久久综合免费视频| 在线观看亚洲a| 免费观看成人鲁鲁鲁鲁鲁视频| 欧美在线999| 亚洲福利专区| 日韩午夜激情| 国产乱肥老妇国产一区二| 欧美中文字幕久久| 久久免费国产| 一区二区三区色| 亚洲精品一区二区在线| 性欧美1819sex性高清| 亚洲天堂免费观看| 国产精品影音先锋| 老司机精品久久| 欧美激情一二区| 亚洲男女毛片无遮挡| 午夜精品理论片| 在线免费不卡视频| 日韩亚洲视频在线| 国产亚洲毛片在线| 亚洲国产黄色片| 国产精品久久久久久模特| 久久久久免费观看| 欧美精品亚洲二区| 欧美一区2区三区4区公司二百| 久久精品三级| 中文无字幕一区二区三区| 午夜亚洲影视| 中文欧美字幕免费| 久久免费观看视频| 亚洲欧美日韩视频二区| 久久久www| 亚洲综合色在线| 久久精品人人爽| 亚洲综合日韩在线| 免费精品99久久国产综合精品| 亚洲一区三区电影在线观看| 欧美一区二区三区男人的天堂| 亚洲全部视频| 久久久久国产一区二区三区四区 | 亚洲日本一区二区三区| 一区二区三区视频观看| 亚洲国产高清在线观看视频| 亚洲一区二区免费看| 亚洲毛片av在线| 久久九九有精品国产23| 亚洲欧美第一页| 欧美日本不卡高清| 欧美.日韩.国产.一区.二区| 国产精品成人va在线观看| 欧美v日韩v国产v| 国产视频一区二区在线观看 | 老司机成人在线视频| 国产精品成人av性教育| 亚洲国产高清自拍| 亚洲国产99精品国自产| 欧美在线不卡视频| 午夜久久一区| 国产精品久久久久久久久久直播| 亚洲国产精品成人| 亚洲欧洲日本mm| 麻豆91精品| 免播放器亚洲一区| 国内欧美视频一区二区| 性欧美18~19sex高清播放| 亚洲欧美日韩专区| 欧美日韩一区二区三区四区五区| 欧美激情精品久久久久久黑人| 在线不卡中文字幕| 久久伊人免费视频| 欧美成人性网| 欧美激情一二三区| 亚洲午夜伦理| 国产精品成人在线| 中国成人黄色视屏| 亚洲欧美中文字幕| 国产欧美一区二区三区久久 | 美女精品在线观看| 免费不卡亚洲欧美| 亚洲欧洲精品天堂一级| 欧美激情中文字幕在线| 亚洲精品美女91| 亚洲欧美久久久| 国产日韩精品一区二区三区在线 | 欧美一区二区三区在线观看视频 | 亚洲色无码播放| 欧美一区二区三区四区视频| 国产精品五月天| 久久国内精品视频| 欧美激情视频一区二区三区在线播放 | 美女网站在线免费欧美精品| 海角社区69精品视频| 美女在线一区二区| 亚洲激情网站| 亚洲欧美伊人| 狠狠色丁香婷婷综合影院| 美女视频网站黄色亚洲| 亚洲精品日产精品乱码不卡| 亚洲欧美日韩系列| 一区二区三区在线视频观看| 欧美激情免费观看| 亚洲欧美日本精品| 亚洲福利一区| 久久黄色小说| 一本色道久久综合亚洲91| 国产精品久久久久久一区二区三区| 亚洲欧美日韩天堂| 亚洲高清二区| 久久超碰97人人做人人爱| 在线日韩av永久免费观看| 欧美日韩中文字幕在线视频| 久久精品国产第一区二区三区| 亚洲激情一区二区三区| 欧美在线播放视频| 亚洲精品在线二区| 国产亚洲永久域名| 欧美日精品一区视频| 久久综合九色九九| 小辣椒精品导航| 日韩午夜一区| 亚洲第一久久影院| 久久在线免费观看视频| 亚洲欧美国内爽妇网| 亚洲精品国产精品国自产观看 | 激情欧美国产欧美| 欧美视频在线观看| 欧美 日韩 国产一区二区在线视频| 亚洲影视在线播放| 亚洲免费成人av| 欧美激情综合| 毛片av中文字幕一区二区| 午夜在线一区二区| 欧美成人精精品一区二区频| 亚洲国产精品成人| 久久在线免费观看| 久久久久久黄| 欧美亚洲自偷自偷|