• <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>
            posts - 131, comments - 12, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Windows Socket編程

            Posted on 2012-12-25 15:10 盛勝 閱讀(614) 評論(0)  編輯 收藏 引用
            http://www.shnenglu.com/bujiwu/archive/2012/09/05/71707.html
            Windows下Socket編程主要包括以下幾部分:
            服務端
               1、初始化Windows Socket庫。
               2、創建Socket。
               3、綁定Socket。
               4、監聽。
               5、Accept。
               6、接收、發送數據。

            客戶端
               1、初始化Windows Socket庫。
               2、創建Socket。
               3、連接Socket。
               4、接收、發送數據。

            服務端每接收到一個客戶端的Socket,則創建一個線程。滿足一個服務端連接多個客戶端。

              1 //Server.cpp
              2 #include <iostream>
              3 #include <Windows.h>
              4 
              5 using namespace std;
              6 
              7 #define  PORT 4000
              8 #define  IP_ADDRESS "192.168.1.145"
              9 
             10 DWORD WINAPI ClientThread(LPVOID lpParameter)
             11 {
             12     SOCKET CientSocket = (SOCKET)lpParameter;
             13     int Ret = 0;
             14     char RecvBuffer[MAX_PATH];
             15 
             16     while ( true )
             17     {
             18         memset(RecvBuffer, 0x00sizeof(RecvBuffer));
             19         Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
             20         if ( Ret == 0 || Ret == SOCKET_ERROR ) 
             21         {
             22             cout<<"客戶端退出!"<<endl;
             23             break;
             24         }
             25         cout<<"接收到客戶信息為:"<<RecvBuffer<<endl;
             26     }
             27 
             28     return 0;
             29 }
             30 
             31 int main(int argc, char* argv[])
             32 {
             33     WSADATA  Ws;
             34     SOCKET ServerSocket, CientSocket;
             35     struct sockaddr_in LocalAddr, ClientAddr;
             36     int Ret = 0;
             37     int AddrLen = 0;
             38     HANDLE hThread = NULL;
             39 
             40     //Init Windows Socket
             41     if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
             42     {
             43         cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
             44         return -1;
             45     }
             46     
             47     //Create Socket
             48     ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
             49     if ( ServerSocket == INVALID_SOCKET )
             50     {
             51         cout<<"Create Socket Failed::"<<GetLastError()<<endl;
             52         return -1;
             53     }
             54 
             55     LocalAddr.sin_family = AF_INET;
             56     LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
             57     LocalAddr.sin_port = htons(PORT);
             58     memset(LocalAddr.sin_zero, 0x008);
             59 
             60     //Bind Socket
             61     Ret = bind(ServerSocket, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
             62     if ( Ret != 0 )
             63     {
             64         cout<<"Bind Socket Failed::"<<GetLastError()<<endl;
             65         return -1;
             66     }
             67 
             68     Ret = listen(ServerSocket, 10);
             69     if ( Ret != 0 )
             70     {
             71         cout<<"listen Socket Failed::"<<GetLastError()<<endl;
             72         return -1;
             73     }
             74 
             75     cout<<"服務端已經啟動"<<endl;
             76 
             77     while ( true )
             78     {
             79         AddrLen = sizeof(ClientAddr);
             80         CientSocket = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &AddrLen);
             81         if ( CientSocket == INVALID_SOCKET )
             82         {
             83             cout<<"Accept Failed::"<<GetLastError()<<endl;
             84             break;
             85         }
             86 
             87         cout<<"客戶端連接::"<<inet_ntoa(ClientAddr.sin_addr)<<":"<<ClientAddr.sin_port<<endl;
             88         
             89         hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)CientSocket, 0, NULL);
             90         if ( hThread == NULL )
             91         {
             92             cout<<"Create Thread Failed!"<<endl;
             93             break;
             94         }
             95 
             96         CloseHandle(hThread);
             97     }
             98 
             99     closesocket(ServerSocket);
            100     closesocket(CientSocket);
            101     WSACleanup();
            102 
            103     return 0;
            104 }

             1 //Client.cpp
             2 #include <iostream>
             3 #include <Windows.h>
             4 
             5 using namespace std;
             6 
             7 #define  PORT 4000
             8 #define  IP_ADDRESS "192.168.1.145"
             9 
            10 
            11 int main(int argc, char* argv[])
            12 {
            13     WSADATA  Ws;
            14     SOCKET CientSocket;
            15     struct sockaddr_in ServerAddr;
            16     int Ret = 0;
            17     int AddrLen = 0;
            18     HANDLE hThread = NULL;
            19     char SendBuffer[MAX_PATH];
            20 
            21     //Init Windows Socket
            22     if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )
            23     {
            24         cout<<"Init Windows Socket Failed::"<<GetLastError()<<endl;
            25         return -1;
            26     }
            27 
            28     //Create Socket
            29     CientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            30     if ( CientSocket == INVALID_SOCKET )
            31     {
            32         cout<<"Create Socket Failed::"<<GetLastError()<<endl;
            33         return -1;
            34     }
            35 
            36     ServerAddr.sin_family = AF_INET;
            37     ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
            38     ServerAddr.sin_port = htons(PORT);
            39     memset(ServerAddr.sin_zero, 0x008);
            40 
            41     Ret = connect(CientSocket,(struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
            42     if ( Ret == SOCKET_ERROR )
            43     {
            44         cout<<"Connect Error::"<<GetLastError()<<endl;
            45         return -1;
            46     }
            47     else
            48     {
            49         cout<<"連接成功!"<<endl;
            50     }
            51 
            52     while ( true )
            53     {
            54         cin.getline(SendBuffer, sizeof(SendBuffer));
            55         Ret = send(CientSocket, SendBuffer, (int)strlen(SendBuffer), 0);
            56         if ( Ret == SOCKET_ERROR )
            57         {
            58             cout<<"Send Info Error::"<<GetLastError()<<endl;
            59             break;
            60         }
            61     }
            62     
            63     closesocket(CientSocket);
            64     WSACleanup();
            65 
            66     return 0;
            67 }

            很幽默的講解六種Windows Socket I/O模型

            老陳有一個在外地工作的女兒,不能經常回來,老陳和她通過信件聯系。他們的信會被郵遞員投遞到他們的信箱里。
            這和Socket模型非常類似。下面我就以老陳接收信件為例講解Socket I/O模型~~~

            一:select模型

            老陳非常想看到女兒的信。以至于他每隔10分鐘就下樓檢查信箱,看是否有女兒的信~~~~~
            在這種情況下,"下樓檢查信箱"然后回到樓上耽誤了老陳太多的時間,以至于老陳無法做其他工作。
            select模型和老陳的這種情況非常相似:周而復始地去檢查......如果有數據......接收/ 發送.......

            使用線程來select應該是通用的做法:
            http://tangfeng.iteye.com/blog/518135

             


            二:WSAAsyncSelect模型

            后來,老陳使用了微軟公司的新式信箱。這種信箱非常先進,一旦信箱里有新的信件,蓋茨就會給老陳打電話:喂,大爺,你有新的信件了!從此,老陳再也不必頻繁上下樓檢查信箱了,牙也不疼了,你瞅準了,藍天......不是,微軟~~~~~~~~
            微軟提供的WSAAsyncSelect模型就是這個意思。

            WSAAsyncSelect 模型是Windows下最簡單易用的一種Socket I/O模型。使用這種模型時,Windows會把網絡事件以消息的形勢通知應用程序。

            http://tangfeng.iteye.com/blog/518141

             

             

            三:WSAEventSelect模型

            后來,微軟的信箱非常暢銷,購買微軟信箱的人以百萬計數......以至于蓋茨每天24小時給客戶打電話,累得腰酸背痛,喝啥都不好使~~~~~~
            微軟改進了他們的信箱:在客戶的家中添加一個附加裝置,這個裝置會監視客戶的信箱,每當新的信件來臨,此裝置會發出"新信件到達"聲,提醒老陳去收信。蓋茨終于可以睡覺了。

            http://tangfeng.iteye.com/blog/518142 

            四:Overlapped I/O 事件通知模型

            后來,微軟通過調查發現,老陳不喜歡上下樓收發信件,因為上下樓其實很浪費時間。于是微軟再次改進他們的信箱。新式的信箱采用了更為先進的技術,只要用戶告訴微軟自己的家在幾樓幾號,新式信箱會把信件直接傳送到用戶的家中,然后告訴用戶,你的信件已經放到你的家中了!老陳很高興,因為他不必再親自收發信件了!

            Overlapped I/O 事件通知模型和WSAEventSelect模型在實現上非常相似,主要區別在"Overlapped",Overlapped模型是讓應用程序使用重疊數據結構(WSAOVERLAPPED),一次投遞一個或多個Winsock I/O請求。這些提交的請求完成后,應用程序會收到通知。什么意思呢?就是說,如果你想從socket上接收數據,只需要告訴系統,由系統為你接收數據,而你需要做的只是為系統提供一個緩沖區~~~~~
            http://tangfeng.iteye.com/blog/518146 

            五:Overlapped I/O 完成例程模型

            老陳接收到新的信件后,一般的程序是:打開信封----掏出信紙----閱讀信件----回復信件......為了進一步減輕用戶負擔,微軟又開發了一種新的技術:用戶只要告訴微軟對信件的操作步驟,微軟信箱將按照這些步驟去處理信件,不再需要用戶親自拆信/閱讀 /回復了!老陳終于過上了小資生活!

            http://tangfeng.iteye.com/blog/518146 

            六:IOCP模型

            微軟信箱似乎很完美,老陳也很滿意。但是在一些大公司情況卻完全不同!這些大公司有數以萬計的信箱,每秒鐘都有數以百計的信件需要處理,以至于微軟信箱經常因超負荷運轉而崩潰!需要重新啟動!微軟不得不使出殺手锏......
            微軟給每個大公司派了一名名叫"Completion Port"的超級機器人,讓這個機器人去處理那些信件!

            "Windows NT小組注意到這些應用程序的性能沒有預料的那么高。特別的,處理很多同時的客戶請求意味著很多線程并發地運行在系統中。因為所有這些線程都是可運行的 [沒有被掛起和等待發生什么事],Microsoft意識到NT內核花費了太多的時間來轉換運行線程的上下文[Context],線程就沒有得到很多 CPU時間來做它們的工作。大家可能也都感覺到并行模型的瓶頸在于它為每一個客戶請求都創建了一個新線程。創建線程比起創建進程開銷要小,但也遠不是沒有開銷的。我們不妨設想一下:如果事先開好N個線程,讓它們在那hold[堵塞],然后可以將所有用戶的請求都投遞到一個消息隊列中去。然后那N個線程逐一從消息隊列中去取出消息并加以處理。就可以避免針對每一個用戶請求都開線程。不僅減少了線程的資源,也提高了線程的利用率。理論上很不錯,你想我等泛泛之輩都能想出來的問題,Microsoft又怎會沒有考慮到呢?"-----摘自nonocast的《理解I/O Completion Port》

            先看一下IOCP模型的實現:

            http://tangfeng.iteye.com/blog/518148 

            IOCP不是一個普通的對象,不需要考慮線程安全問題。它會自動調配訪問它的線程:如果某個socket上有一個線程A正在訪問,那么線程B的訪問請求會被分配到另外一個socket。這一切都是由系統自動調配的,我們無需過問。

            久久成人国产精品免费软件| 99久久免费国产精品热| 精品国产青草久久久久福利| 国产免费久久精品99久久| 久久久精品久久久久久| 久久影视国产亚洲| 狼狼综合久久久久综合网| 国产AV影片久久久久久 | 久久精品国产欧美日韩99热| 国产69精品久久久久APP下载| 人妻精品久久无码区| 久久久久人妻精品一区三寸蜜桃 | 久久精品国产亚洲AV不卡| 国产成年无码久久久免费| 热99re久久国超精品首页| 91麻豆国产精品91久久久| 久久精品嫩草影院| 精品人妻伦九区久久AAA片69| 嫩草影院久久国产精品| 77777亚洲午夜久久多喷| 韩国三级中文字幕hd久久精品| 色婷婷综合久久久久中文| 欧美精品福利视频一区二区三区久久久精品 | 精品综合久久久久久98| 国产精品内射久久久久欢欢 | 国产精品欧美亚洲韩国日本久久 | 久久久国产精华液| 97久久精品无码一区二区 | 久久久久亚洲精品无码网址| 国产精品美女久久久m| 亚洲AV无码1区2区久久| 亚洲精品乱码久久久久久不卡| 88久久精品无码一区二区毛片 | 久久久久人妻一区二区三区| 久久精品国产一区二区三区不卡| 国产∨亚洲V天堂无码久久久| 亚洲国产天堂久久综合| 久久综合精品国产一区二区三区| 国产精品永久久久久久久久久| 丰满少妇人妻久久久久久4| 久久精品国产亚洲麻豆|