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

隨筆-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>
            亚洲一品av免费观看| 六月天综合网| 久久久精品日韩欧美| 亚洲欧美怡红院| 亚洲一区国产视频| 久久国产精品久久精品国产| 久久久亚洲人| 亚洲国产精品嫩草影院| 亚洲激情综合| 亚洲无人区一区| 久久精品国产一区二区三区免费看 | 久久字幕精品一区| 亚洲盗摄视频| 中文网丁香综合网| 久久国产精品99国产| 欧美大片免费久久精品三p| 欧美日韩国产精品一区| 国产麻豆一精品一av一免费| 国产日韩精品视频一区二区三区| 欧美亚洲综合另类| 久久青草福利网站| 欧美日韩一区国产| 黄网动漫久久久| 一本色道久久综合亚洲精品小说 | 国产精品久久| 一区二区三区亚洲| 亚洲图片欧洲图片av| 久久久免费观看视频| 亚洲人成在线观看| 欧美亚洲视频| 欧美三区在线视频| 在线播放日韩| 亚洲永久免费观看| 亚洲黄色免费电影| 久久精品国产精品| 国产精品自拍小视频| 最新成人在线| 美女黄毛**国产精品啪啪| 国产精品99久久久久久久久| 免费在线亚洲欧美| 永久555www成人免费| 国产精品福利片| 99精品国产99久久久久久福利| 国产美女诱惑一区二区| 欧美国产日产韩国视频| 中文在线不卡| 美女主播一区| 国产一区二区三区视频在线观看| 一本久久综合亚洲鲁鲁五月天| 免费日本视频一区| 香蕉av777xxx色综合一区| 欧美美女日韩| 91久久精品网| 蜜桃久久精品乱码一区二区| 午夜视频一区| 国产精品入口麻豆原神| 亚洲一区日本| 亚洲一区二区成人在线观看| 欧美日韩高清在线播放| 亚洲欧美国产日韩天堂区| 久久精品国产综合精品| 国产欧美一区二区三区在线看蜜臀| 夜夜爽99久久国产综合精品女不卡| 欧美大片免费观看| 久久一区亚洲| 亚洲国产精品电影在线观看| 欧美**字幕| 欧美成人免费观看| 一本久久综合亚洲鲁鲁| 日韩视频一区二区| 国产精品视频yy9099| 久久九九热re6这里有精品| 国产私拍一区| 亚洲手机成人高清视频| 99国产一区| 欧美三区在线| 性色av一区二区怡红| 亚洲一区成人| 国产一区二区视频在线观看| 久久婷婷麻豆| 欧美国产成人精品| 亚洲欧美影音先锋| 久久久噜久噜久久综合| 一本久久综合亚洲鲁鲁五月天| 中文久久精品| 一区二区视频免费完整版观看| 欧美韩日一区二区| 欧美日韩中文字幕| 久久成人免费电影| 免费国产一区二区| 亚洲一区在线播放| 久久久综合网| 亚洲一区中文字幕在线观看| 欧美专区日韩视频| 99在线精品视频| 欧美一区二区三区四区视频| 亚洲精品一区二区三区福利| 亚洲综合视频在线| 亚洲精品一区二区三区蜜桃久| 一区二区三区免费看| 亚洲动漫精品| 亚洲影院色在线观看免费| 亚洲高清在线视频| 亚洲一区三区电影在线观看| 亚洲国产成人av| 亚洲欧美中文字幕| 一区二区三区黄色| 免费不卡在线视频| 久久久精品一品道一区| 欧美日韩在线播放一区二区| 你懂的国产精品| 国产日韩在线一区二区三区| 99riav1国产精品视频| …久久精品99久久香蕉国产| 亚洲自拍偷拍麻豆| 一区二区三区 在线观看视| 久久亚洲色图| 久久精品五月婷婷| 国产精品亚洲人在线观看| 亚洲美洲欧洲综合国产一区| 亚洲高清免费视频| 久久久精品欧美丰满| 欧美一区=区| 国产精品国产三级国产普通话99 | 国产日韩精品电影| 日韩一二三区视频| 欧美国产精品一区| 蜜桃av噜噜一区| 狠狠色丁香久久婷婷综合丁香| 亚洲欧美第一页| 久久国产精品久久国产精品| 国产一区二区| 久久亚洲一区二区| 国产一区日韩一区| 小黄鸭视频精品导航| 欧美亚洲综合网| 中国亚洲黄色| 国产主播一区二区三区四区| 久久都是精品| 国产精品一区二区久久久久| 日韩一级黄色大片| 国产精品99久久久久久有的能看| 欧美激情一区二区三区在线视频| 欧美电影在线观看完整版| 在线免费观看欧美| 久久午夜精品一区二区| 欧美成人免费在线| 亚洲精品国产精品国自产在线| 欧美激情va永久在线播放| 亚洲国产视频直播| 一区二区三区三区在线| 蜜臀久久99精品久久久久久9 | 久久久99久久精品女同性| 亚洲国产欧美久久| 亚洲一级黄色av| 亚洲一区久久| 老色鬼久久亚洲一区二区| 国产精品久久久久国产精品日日| 亚洲国产精品毛片| 亚洲黄色在线观看| 久久精品国产2020观看福利| 国产午夜精品全部视频播放| 亚洲欧美中文日韩在线| 亚洲主播在线播放| 国产精品视频网址| 欧美一级播放| 欧美一区二区三区日韩视频| 国产一区再线| 亚洲国产另类久久精品| 免费91麻豆精品国产自产在线观看| 亚洲大胆女人| 免费91麻豆精品国产自产在线观看| 久久精品亚洲一区| 噜噜噜91成人网| 亚洲小说区图片区| 免费欧美日韩国产三级电影| 亚洲日韩欧美视频一区| 欧美午夜一区二区三区免费大片| 香蕉尹人综合在线观看| 欧美黄色日本| 欧美伊人久久久久久久久影院| 欧美一级网站| 午夜精品影院在线观看| 久久国产66| 在线亚洲激情| 精品动漫一区| 国产精品久久久久久久久搜平片 | 国产日韩一区二区三区| 免费观看亚洲视频大全| 亚洲制服av| 亚洲精品久久| 美女视频网站黄色亚洲| 欧美在线免费观看| 亚洲午夜影视影院在线观看| 亚洲国产高清一区二区三区| 国产精品夜色7777狼人| 欧美日本国产视频| 欧美 日韩 国产在线| 久久久久成人精品| 欧美亚洲免费|