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

隨筆-250  評論-20  文章-55  trackbacks-0
 重疊I/O也是一種異步I/O,同樣也支持Win32的其它對象,當然在Winsock中可以發揮很大的作用。使用Overlapped開發支持一定數量的Socket的應用,效率是相當很高的。但就我個人的觀點,在Win32下做網絡應用的開發,如果要支持100個以上的Socket的話,還是考慮Completion Port I/O。要求支持Socket最好是100個以下,我是基于這樣考慮的:Overlapped是通過多線程支持多Socket的,如果開辟的線程太多的話,勢必影響了系統的性能;Completion Port I/O可以更好支持大量的客戶端。這兩種在Windows下具有高效率的I/O都不支持Windows CE及其它平臺。我在這里說一下在開發網絡應用時什么時候用Overlapped I/O 模型:準備在Win98和以上版本或WinNT3.1和以上版本做開發,且要求支持Socket最好在100個以下。另外在串口開發中,考慮效率問題,有很多地方用到了Overlapped I/O。
         Overlapped I/O主要涉及一個數據結構Overlapped(Winsock中是WSAOverlapped)和一個函數WSAGetOverlappedResult(..)。
         Overlapped I/O執行步驟很清晰,只要下面三步:
         (1) 應用先通過WSASend或WSARecv(不知道有沒有其它的請求,我只用過這兩個函數),注意要向兩者轉入WSAOverlapped參數,
表示,執行的是Overlapped操作;
         (2)在一個循環中,調用GetOverlappedResult(..)等待操作完成,GetOverlappedResult返回時,進行相應的處理,如處理數據;
         (3) 最后,還在(2)循環中,發送另外一個請求(WSASend或WSARecv),重復處理(2)、(3)兩步。
        第一步中執行WSASend或WSARecv時,函數立即返回,得到SOCKET_ERROR信息且此時WSAGetErrorLast返回WSA_IO_PENDING,說明調用已成功,Winsock正在處理WSASend或WSARecv的請求。個人認為Winsock在內部開辟了新的線程處理,應用程序不用管理多線程,達到異步的目的,有利于性能的提高。WSASend或WSARecv也可能返回"0",表示立即成功,這時,應用還是可以在WSAGetOverlappedResult()處等待,處理過程與上面是一樣的;也就是說我們不須要馬上在WSASend或WSARecv進行相關的處理。
        WSAGetOverlappedResult返回FASLE且WSAGetLastError返回WSA_IO_INCOMPLETE,表示處理正在進行中。   

        下面我給出支持單個Socket及支持多個Socket的Console程序代碼。先來看看支持單個Socket的程序,考慮到代碼簡潔性,只給一個框架,同時不進行出錯處理。
int main()
{
          WSAOVERLAPPED     Overlapped;
                  
          // 啟動Winsock及建立監聽套接字
           listen(hListenSocket,  5);
       
           hClientSocket   =   accept(hListenSocket,   NULL,   NULL);
           ZeroMemory(&Overlapped,   sizeof(WSAOVERLAPPED));
           
           nResult   =   WSARecv(...);    // 發出請求
        
          for (; ;)
          {
                   bResult   =   WSAGetOverlappedResult(...);
                   // 函數返回后進行相應的處理
                   nResult   =   WSARecv(...);  // 發出另外一個請求
          }
}
        上面的程序只是想說明一下過程,程序沒有實現什么功能。這樣做的目的是節約字數,用來說明我下面支持多個Socket的Console應用。請繼續看。
        先看一個自定義的結構體,單句柄數據結構,通過該結構,主線程與某個特定的子線程中的套接字相互聯系。
         typedef   struct    _PER_HANDLE_DATA
         {
                   SOCKET   hSocket;     // 主鍵:通信套接字
                  char    szClientIP[16];// 自定義字段:客戶端地址
                  int nOperateType;   // 自定義字段:操作類型
          }PER_HANDLE_DATA,   FAR*  LPPER_HANDLE_DATA;
         在上面的結構中還可以加入自己需要的字段。在我下面的例子程序中,szClientIP是用來保存連接上來的客戶端的IP的,這樣在主線程將這個結構體傳給子線程后,在子線程中根據客戶端IP就知道目前處理的是哪個客戶端了。下面是程序的大部分,同樣除去一些簡單的出錯輸出。
#define     LISTEN_PORT 5000
#define     DATA_BUFSIZE 8192
#define     POST_RECV 0X01   
#define     POST_SEND 0X02

int   main(  )
{
           LPPER_HANDLE_DATA    lpPerHandleData;
           SOCKET               hListenSocket;
           SOCKET               hClientSocket;
           SOCKADDR_IN          ClientAddr;
           int                  nAddrLen;
           HANDLE               hThread; 

          // Start WinSock and create a listen socket.

          listen(hListenSocket,  5); 
          for (; ;)
         {
                  nAddrLen  =  sizeof(SOCKADDR);
                  hClientSocket  =  accept(hListenSocket,  (LPSOCKADDR)&ClientAddr,  &nAddrLen);

                  lpPerHandleData = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
                  lpPerHandleData->hSocket  =  hClientSocket;
                  // 注意這里將連接的客戶端的IP地址,保存到了lpPerHandleData字段中了
                 strcpy(lpPerHandleData->szClientIP,   inet_ntoa(ClientAddr.sin_addr));

                 // 為本次客戶請求產生子線程
                 hThread = CreateThread(
                           NULL,
                           0,
                           OverlappedThread,
                           lpPerHandleData,   // 將lpPerHandleData傳給子線程
                           0,
                           NULL
                  );
                 CloseHandle(hThread);
         }   
 return 0;
}

DWORD   WINAPI   OverlappedThread(LPVOID    lpParam)
{
            LPPER_HANDLE_DATA     lpPerHandleData   =   (LPPER_HANDLE_DATA)lpParam;
            WSAOVERLAPPED Overlapped;
            WSABUF        wsaBuf;
            char          Buffer[DATA_BUFSIZE];
            BOOL          bResult;
            int           nResult;
   
            ZeroMemory(&Overlapped, sizeof(WSAOVERLAPPED));
            wsaBuf.buf = Buffer;
            wsaBuf.len = sizeof(Buffer);
            lpPerHandleData->nOperateType = POST_RECV;     // 記錄本次操作是Recv(..)

            dwFlags = 0;
            nResult = WSARecv(
                      lpPerHandleData->hSocket,   // Receive socket
                      &wsaBuf,                                  // 指向WSABUF結構的指針
                      1,                                                 // WSABUF數組的個數
                      &dwNumOfBytesRecved,      // 存放當WSARecv完成后所接收到的字節數
                      &dwFlags,                                 // A pointer to flags
                      &Overlapped,                           // A pointer to a WSAOVERLAPPED structure
                      NULL                                         // A pointer to the completion routine,this is NULL
           );
          if   ( nResult   ==   SOCKET_ERROR     &&   GetLastError() !=       WSA_IO_PENDING)
          {
                 printf("WSARecv(..) failed.\n");
                 free(lpPerHandleData);
                 return 1;
          }

         while (TRUE)
         {
                 bResult  =  WSAGetOverlappedResult(
                        lpPerHandleData->hSocket,  
                        &Overlapped,           
                        &dwBytesTransferred,       // 當一個同步I/O完成后,接收到的字節數
                       TRUE,                      // 等待I/O操作的完成
                       &dwFlags                   
                 );
                if   (bResult  ==  FALSE  &&  WSAGetLastError()  !=  WSA_IO_INCOMPLETE)
               {
                         printf("WSAGetOverlappdResult(..) failed.\n");
                         free(lpPerHandleData);
                         return 1;   // 錯誤退出
                }
        
                if  (dwBytesTransferred == 0)
                {
                           printf("客戶端已退出,將斷開與之的連接!\n");
                           closesocket(lpPerHandleData->hSocket);
                           free(lpPerHandleData);
                           break;
                }

                 // 在這里將接收到的數據進行處理
               printf("Received from IP: %s.\ndata: %s\n", lpPerHandleData->szClientIP, wsaBuf.buf);    

               // 發送另外一個請求操作
               ZeroMemory(&Overlapped, sizeof(WSAOVERLAPPED));
               lpPerHandleData->nOperateType = POST_RECV;

               dwFlags = 0;
                nResult = WSARecv(...);
                if (...)
{}

         }

         return 0;
}
         程序結構比較清晰,lpPerHandleData是主線程與子線程聯系的紐帶,子線程是通過這個結構獲得所處理客戶端的情況的。在不同的應用中可以將這個結構定義成不同的形式,以符合所實現應用的需要。注意結構體的nOperateType在GetOverlappedResult返回時用到,可以根據這個字段確定我們下一步的操作。請朋友們多提意見了。

posted on 2007-04-10 18:06 jay 閱讀(3169) 評論(0)  編輯 收藏 引用 所屬分類: socket
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产又爽又黄的激情精品视频| 欧美亚洲一区| 亚洲美女一区| 欧美日韩亚洲激情| 久久精品视频在线| 国产精品成人一区二区三区吃奶| 亚洲一区二区动漫| 欧美jizzhd精品欧美巨大免费| 亚洲精品欧美一区二区三区| 日韩手机在线导航| 国产一区二区在线免费观看| 国产专区欧美专区| 亚洲在线免费视频| 午夜国产精品视频免费体验区| 亚洲在线不卡| 久久九九精品99国产精品| 久久乐国产精品| 91久久久亚洲精品| 欧美中文字幕在线播放| 亚洲毛片在线观看| 日韩手机在线导航| 日韩天堂av| 亚洲精品综合久久中文字幕| 国产香蕉97碰碰久久人人| 欧美日本国产| 欧美日韩高清不卡| 国产伦精品一区二区三区照片91 | 欧美国产日韩一区二区在线观看| 欧美大片免费| 久久精品视频免费观看| 美女亚洲精品| 亚洲精品网站在线播放gif| 亚洲国产黄色| 最新日韩欧美| 久久国产主播| 国产精品国产三级国产aⅴ浪潮| 亚洲精品视频在线观看网站| 国产日韩成人精品| 午夜精彩国产免费不卡不顿大片| 亚洲国产高清aⅴ视频| 欧美激情综合网| 激情婷婷久久| 久久精品人人做人人综合| 欧美mv日韩mv国产网站app| 亚洲欧洲在线免费| 老牛国产精品一区的观看方式| 亚洲一级片在线看| 性欧美大战久久久久久久久| 久久成人免费| 一区二区三区日韩精品视频| 欧美一级播放| 国产精品久久久久毛片大屁完整版 | 99精品久久| 久久精品国产在热久久| 国产精品黄色| 亚洲午夜精品一区二区三区他趣| 亚洲国产精品久久久久| 久久免费国产精品1| 国产欧美亚洲一区| 午夜精品短视频| 亚洲午夜免费视频| 国产精品免费电影| 欧美一区二区视频在线| 亚洲在线一区二区| 国产精品私房写真福利视频| 亚洲一区久久久| 中文在线资源观看网站视频免费不卡 | 欧美呦呦网站| 亚洲视频精品| 欧美日韩一级视频| 中文在线资源观看网站视频免费不卡| 亚洲第一黄网| 欧美色区777第一页| 亚洲综合成人婷婷小说| 亚洲尤物精选| 韩日欧美一区二区三区| 欧美成人在线影院| 欧美日韩精品国产| 欧美在线www| 麻豆精品一区二区av白丝在线| 亚洲日本中文字幕| 在线视频精品一| 国产欧美在线看| 欧美激情视频在线播放| 欧美视频网址| 久久躁日日躁aaaaxxxx| 欧美激情黄色片| 欧美一区成人| 美女黄色成人网| 亚洲欧美自拍偷拍| 免费成人高清在线视频| 欧美chengren| 亚洲人成艺术| 亚洲一区精品电影| 亚洲国产毛片完整版| 亚洲精品在线观看视频| 国产偷国产偷亚洲高清97cao| 久久综合中文字幕| 欧美三区美女| 欧美www在线| 国产精品免费看| 亚洲精品小视频在线观看| 国产一区二区精品久久99| 91久久久精品| 黑人巨大精品欧美黑白配亚洲 | 日韩午夜激情| 欧美永久精品| 亚洲一区中文| 蜜月aⅴ免费一区二区三区 | 亚洲精品孕妇| 尤物在线观看一区| 亚洲资源av| av不卡在线看| 久久综合网络一区二区| 欧美一区二区三区在线视频| 欧美激情视频一区二区三区在线播放 | 久久本道综合色狠狠五月| 亚洲毛片视频| 久久激情网站| 亚洲永久免费| 欧美成人免费小视频| 欧美一级网站| 欧美日韩国产免费观看| 久久人人精品| 国产精品乱子乱xxxx| 亚洲国产成人在线视频| 国产午夜精品一区二区三区视频 | 亚洲高清精品中出| 亚洲美女一区| 亚洲国产小视频| 久久久久成人精品免费播放动漫| 午夜精品一区二区三区四区| 欧美日韩黄视频| 夜夜嗨av色一区二区不卡| 亚洲久久成人| 欧美精品久久久久a| 亚洲国产精品视频一区| 91久久久亚洲精品| 欧美激情精品久久久久| 亚洲青色在线| 99国产精品久久久久老师| 欧美成人一品| 亚洲人成网站999久久久综合| 亚洲欧洲精品一区| 欧美国产激情| 一级成人国产| 亚洲欧美日本精品| 国产欧美精品一区二区色综合 | 小黄鸭精品密入口导航| 欧美一区二区性| 美腿丝袜亚洲色图| 亚洲国产清纯| 欧美日韩一级视频| 欧美亚洲自偷自偷| 另类综合日韩欧美亚洲| 亚洲国产日韩综合一区| 欧美激情一区二区三区蜜桃视频 | 欧美激情久久久久久| 亚洲三级毛片| 欧美日韩亚洲一区二区三区| 99国产精品| 久久久91精品国产一区二区三区| 国产综合自拍| 欧美久色视频| 欧美一级午夜免费电影| 欧美不卡视频一区| 亚洲一区尤物| 亚洲二区免费| 国产精品草草| 久久综合一区二区三区| 日韩一级裸体免费视频| 久久久久九九九九| 99在线|亚洲一区二区| 国产精品主播| 欧美极品一区二区三区| 午夜精品网站| 亚洲欧洲综合| 亚洲一区一卡| 久久久国产成人精品| 亚洲国产精品视频| 国产精自产拍久久久久久| 乱人伦精品视频在线观看| 亚洲午夜精品久久| 欧美激情1区| 久久九九国产| 亚洲免费在线视频一区 二区| …久久精品99久久香蕉国产| 国产精品久久久999| 欧美大色视频| 久久成人一区| 亚洲深夜影院| 亚洲国产日韩在线一区模特| 久久gogo国模裸体人体| 亚洲图片欧美日产| 亚洲精品黄网在线观看| 精品成人在线| 国内视频精品| 国产亚洲精品久久久久婷婷瑜伽| 欧美揉bbbbb揉bbbbb| 欧美成人一区二区三区在线观看|