• <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>
            隨筆 - 96  文章 - 255  trackbacks - 0
            <2008年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            E-mail:zbln426@163.com QQ:85132383 長期尋找對戰略游戲感興趣的合作伙伴。

            常用鏈接

            留言簿(21)

            隨筆分類

            隨筆檔案

            SDL相關網站

            我的個人網頁

            我的小游戲

            資源下載

            搜索

            •  

            積分與排名

            • 積分 - 493118
            • 排名 - 39

            最新評論

            閱讀排行榜

            評論排行榜

            作者:龍飛

                    話題回到“黑社會辦公室”的例子,講概念已經扯得比較遠了,不過,這一節我們還得講概念,不過好在有些程序的例子。如果大家不想翻回去看TcpServer類的原型,我這里直接給出這個頭文件的完整源代碼:
            //Filename: TcpServerClass.hpp

            #ifndef TCPSERVERCLASS_HPP_INCLUDED
            #define TCPSERVERCLASS_HPP_INCLUDED

            #include 
            <unistd.h>
            #include 
            <iostream>
            #include 
            <sys/socket.h>
            #include 
            <arpa/inet.h>

            class TcpServer
            {
            private:
                
            int listenSock;
                
            int communicationSock;
                sockaddr_in servAddr;
                sockaddr_in clntAddr;
            public:
                TcpServer(
            int listen_port);
                
            bool isAccept();
                
            void handleEcho();
            };


            #endif // TCPSERVERCLASS_HPP_INCLUDED
            我們已經解釋了為什么listenSock和communicationSock的類型是int,以及sockaddr_in是什么結構,現在來寫這個類的構造函數:
            TcpServer::TcpServer(int listen_port)
            {
                
            if ( (listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) {
                    
            throw "socket() failed";
                }

                memset(
            &servAddr, 0sizeof(servAddr));
                servAddr.sin_family 
            = AF_INET;
                servAddr.sin_addr.s_addr 
            = htonl(INADDR_ANY);
                servAddr.sin_port 
            = htons(listen_port);

                
            if ( bind(listenSock, (sockaddr*)&servAddr, sizeof(servAddr)) < 0 ) {
                    
            throw "bind() failed";
                }

                
            if ( listen(listenSock, 10< 0 ) {
                    
            throw "listen() failed";
                }
            }
            好,先看看程序培養一下感覺,我們還得說概念。

            數據封裝(Data Encapsutation)

                    我們前面說到了網絡分層:鏈路——網絡——傳輸——應用。數據從應用程序里誕生,傳送到互聯網上每一層都會進行一次封裝:
            Data>>Application>>TCP/UDP>>IP>>OS(Driver, Kernel & Physical Address)
            我們用socket重點描述的是協議,包括網絡協議(IP)和傳輸協議(TCP/UDP)。
            sockaddr重點描述的是地址,包括IP地址和TCP/UDP端口。

            socket()函數

                我們從TcpServer::TcpServer()函數可以看到,socket和sockaddr的產生是可以相互獨立的。socket()的函數原型是:
            int socket(int protocolFamily, int type, int protocol);
            在Linux中的實現為:
            #include <sys/socket.h>

            /* Create a new socket of type TYPE in domain DOMAIN, using
               protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
               Returns a file descriptor for the new socket, or -1 for errors.  
            */
            extern int socket (int __domain, int __type, int __protocol) __THROW;
            第一個參數是協議簇(Linux里面叫作域,意思一樣的),還是那句話,我們這篇教程用到的就僅僅是一個PF_INET(protocol family : internet),很多時候你會發現人們也經常在這里賦值為AF_INET,事實上,當前,AF_INET就是PF_INET的一個#define,但是,寫成PF_INET從語義上會更加嚴謹。這也就是TCP/IP協議簇中的IP協議(Internet Protocol),網絡層的協議。
            后面兩個參數定義傳輸層的協議。
            第二個參數是傳輸層協議類型,我們教程里用到的宏,只有兩個:SOCK_STREAM(數據流格式)和SOCK_DGRAM(數據報格式);(具體是什么我們以后討論)
            第三個參數是具體的傳輸層協議。當賦值為0的時候,系統會根據傳輸層協議類型自動匹配和選擇。事實上,當前,匹配SOCK_STREAM的就是TCP協議;而匹配SOCK_DGRAM就是UDP協議。所以,我們指定了第二個參數,第三個就可以簡單的設置為0。不過,為了嚴謹,我們最好還是把具體協議寫出來,比如,我們的例子中的TCP協議的宏名稱:IPPROTO_TCP。

            數據的“地址”

                    從數據封裝的模型,我們可以看到數據是怎么從應用程序傳遞到互聯網的。我們說過,數據的傳送是通過socket進行的。但是socket只描述了協議類型。要讓數據正確的傳送到某個地方,必須添加那個地方的sockaddr地址;同樣,要能接受網絡上的數據,必須有自己的sockaddr地址。
                    可見,在網絡上傳送的數據包,是socket和sockaddr共同“染指”的結果。他們共同封裝和指定了一個數據包的網絡協議(IP)和IP地址,傳輸協議(TCP/UDP)和端口號。

            網絡字節和本機字節的相互轉換

                    sockaddr結構中的IP地址(sin_addr.s_addr)和端口號(sin_port)將被封裝到網絡上傳送的數據包中,所以,它的結構形式需要保證是網絡字節形式。我們這里用到的函數是htons()和htonl(),這些縮寫的意思是:
            h: host,主機(本機)
            n: network,網絡
            to: to轉換
            s: short,16位(2字節,常用于端口號)
            l: long, 32位(4字節,常用于IP地址)
            “反過來”的函數也是存在的ntohs()和ntohl()。

            動作與持續行為

                    本節最后的一個概念可以跟計算機無關。作為動詞,有些可以描述動作,有些是描述一重持續的行為狀態的(就如同一般動詞和be動詞一樣)。扯到C++來說,我們可以把持續行為封裝到函數內部,只留出動作的接口。事實上,構造函數中的bind()和listen()就是這種描述持續狀態的行為函數。

            posted on 2008-07-12 13:27 lf426 閱讀(5146) 評論(0)  編輯 收藏 引用 所屬分類: SDL入門教程Linux與C++socket 編程入門教程
            久久久噜噜噜久久中文字幕色伊伊 | 亚洲中文字幕久久精品无码APP | 午夜精品久久久久久中宇| 伊人久久大香线蕉综合Av| 久久r热这里有精品视频| 人人狠狠综合久久亚洲88| 久久播电影网| 三上悠亚久久精品| 久久―日本道色综合久久| 久久99热这里只频精品6| 国产成人精品免费久久久久| 国产精品成人99久久久久| 亚洲欧美一区二区三区久久| 9久久9久久精品| 久久婷婷是五月综合色狠狠| 久久免费美女视频| 香蕉久久夜色精品升级完成| 国产精品99久久精品爆乳| 婷婷伊人久久大香线蕉AV| 久久精品99无色码中文字幕| 久久久久亚洲AV片无码下载蜜桃| 精品视频久久久久| 青青草国产成人久久91网| 精品国产一区二区三区久久久狼 | 99久久精品国内| 亚洲国产精品久久电影欧美| 久久综合亚洲色HEZYO国产| 99久久伊人精品综合观看| 久久亚洲国产成人精品性色| 亚洲狠狠婷婷综合久久久久| 无码八A片人妻少妇久久| 亚洲国产成人乱码精品女人久久久不卡 | 99久久国产宗和精品1上映| 性高湖久久久久久久久AAAAA| 91精品国产91久久久久久| 69久久夜色精品国产69 | 欧美成a人片免费看久久| 国产2021久久精品| 91久久九九无码成人网站 | 久久婷婷五月综合国产尤物app| 久久久久亚洲AV无码专区首JN|