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

隨筆 - 97, 文章 - 22, 評論 - 81, 引用 - 0
數據加載中……

網絡編程路漫漫(一)啟程

一、套接字
      1、什么是套接字(socket)
      2、創建套接字
            1) 協議族(Protocol Family)
            2) 套接字類型
            3) 協議確定
      3、分配IP和端口
            1) IP(Internet Protocol)
            2) 端口
            3) 地址信息詳解
            4) 主機字節序/網絡字節序
            5) 綁定IP和端口
二、基于TCP的服務器端
      1、TCP/IP協議
      2、TCP服務器主流程
      3、等待連接請求
      4、受理請求
      5、數據交換
      6、斷開連接
      7、調試工具
三、基于TCP的客戶端
      1、TCP客戶端主流程
      2、請求連接
四、回顧主流程

 一、套接字
        1、什么是套接字(socket)
        首先,我不想闡述太多的概念,直接拿例子說話最實際,說得越多就越亂。那么讓我們先來看一個概念(囧),網絡編程。
        網絡編程就是編寫程序將兩臺連網的計算機實現數據交換。如何進行數據交換?首先需要物理連接,這個不是我們程序員需要關心的事情,我們需要關心的是如何編寫數據傳輸軟件。操作系統為我們提供了“套接字”(socket)模塊來干這件事。
        套接字是網絡數據傳輸用的軟件設備。更加直白的解釋是這樣的:網絡上兩個程序通過一個雙向的通信連接實現數據交換,這個連接的一端稱為一個套接字。
        2、創建套接字
        好了,概念貌似是比較清晰了的樣子,那么讓我們來看看套接字到底是個什么鬼。
        創建套接字的函數如下:
                int socket(int domain, int type, int protocol);
                          成功時返回文件描述符,失敗時返回-1。
        這個函數是操作系統提供的,用于創建一個套接字的內核對象(內核對象是指由操作系統創建的一系列資源,比如進程、線程、文件、套接字、信號量、互斥量等等)。返回值是一個文件描述符,可以簡單的理解為一個ID。如果熟悉MFC的話,我們會發現Windows開發時創建窗口返回的是一個叫“句柄”的東西。沒錯了,Linux上叫文件描述符,Windows上叫句柄。
        這里有必要講一下文件描述符和socket的關系,因為在Linux下socket操作和文件操作沒有區別,即socket也是文件的一種(Windows下并非如此)。文件描述符是系統分配給文件或套接字的整數。在stdio.h頭文件下有三個預定義的文件描述符:
    #define stdin  (&__iob_func()[0])
    #define stdout (&__iob_func()[1])
    #define stderr (&__iob_func()[2])
         即0代表標準輸入,1代表標準輸出,2代表標準錯誤。所以應用程序申請的socket編號從3開始。
         接下來解釋下socket創建時用到的參數:
         domain 代表套接字中使用的協議族,type 代表套接字數據傳輸類型,protocol 代表通信協議。這樣一解釋,是不是本來還有點理解,現在完全懵逼了?不要緊張,一個一個來解釋。
            1)協議族(Protocol Family)
         能用圖的時候堅決不寫字,所以就有了下面這個圖。
 
圖一-2-1
        IPv4是互聯網協議的第四版,也是第一個被廣泛使用,構成現今互聯網技術的基礎的協議。所以我們著重講解PF_INET,其它的暫且可以不管了,是不是很開心?
            2)套接字類型
        套接字類型決定了數據傳輸方式。總共有兩種:SOCK_STREAM創建面向連接的套接字、SOCK_DGRAM創建面向消息的套接字。
        SOCK_STREAM:
            面向連接,可以理解成一條傳送帶,只要這條傳送帶質量沒有問題(也就是網一直連著),那么傳送帶上的物品就不會丟失,較晚的物品不會先到達(傳送帶的保序特性),并且傳輸的物品不存在數據邊界:即發送方和接收方的發送/接收的動作并非一一對應,比如發送方在傳送帶起點連續多次放了一些物品,接收方可以只通過一次操作就取走所有物品。這是因為發送和接收數據有一個內部緩沖(buffer),發送方的數據通過發送方的輸出緩沖存放至接收方的輸入緩沖,如果接收方不取走數據,這些數據就一直在它的輸入緩沖中。緩沖滿了會提供數據重傳機制,所以面向連接的套接字不會存在數據丟失。一句話概括:
            可靠、保序、面向連接的數據傳輸方式的套接字。
        SOCK_DGRAM:
            面向消息,可以理解成快遞。快遞運送過程有可能丟失,不同快遞公司運送的速度不同,所以無法保證先寄出的快遞先到達,并且發送一個快遞,接收的也是一個,因此有數據邊界。而且必須限制快遞的大小。一句話概括:
            不可靠、不保序、以高速數據傳輸為目的的套接字。
            3)協議確定
        參數PF_INET指定的IPv4協議族中,指定SOCK_STREAM面向連接的傳輸方式,滿足前兩個條件的協議只有IPPROTO_TCP,因此可以如下調用創建:
        int tcp_sock = socket(PF_INET, SOCK_STREAM, 0);
        參數PF_INET指定的IPv4協議族中,指定SOCK_DGRAM面向消息的傳輸方式,滿足前兩個條件的協議只有IPPROTO_UDP,因此可以如下調用創建:
        int udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
        因為兩種socket都只有一種協議,所以第三個參數可以省略。
        那么什么時候用TCP,什么時候用UDP呢?來日方長。先賣個關子。這里先以TCP連接為例子進行展開。
        3、分配IP和端口
        上面講了一大堆,竟然只講了一個socket的創建,看來我還是太啰嗦了。那么,既然啰嗦了,就再啰嗦幾句吧(囧)。創建完的套接字需要綁定一個網絡地址,這樣網絡的兩端才能進行通信。
        綁定套接字網絡地址的函數如下:
                int bind(int sockfd, struct sockaddr* addr, socket_t addrlen);
                          成功時返回0,失敗時返回-1。
         第一個參數就是我們創建的那個套接字ID(文件描述符),第二個參數就說來話長了,首先來看下sockaddr這個結構體的定義:
                struct sockaddr {
          unsigned short sin_family;       /* Address family */
          char sa_data[14];                /* 14 bytes of protocol address */
      };

         看完了嗎?
         不說話就是看完了,那我們再來看另一個?
                struct sockaddr_in {
          unsigned short sin_family;       /* Address family */
          unsigned short sin_port;         /* Port number */
          struct in_addr sin_addr;         /* Internet address */
          unsigned char sin_zero[8];       /* Same size as struct sockaddr */
      };

         嗯,細心的你應該發現了,還有一個結構體沒有定義。
                struct in_addr {
            unsigned int s_addr;            /* Internet address */
      };
         現在開始科普,1個sockaddr結構體的總字節數為16(2+14),sockaddr_in的總字節數也是16(2+2+4+8)。所以兩者可以通過取地址后用指針進行強制轉換(C/C++中的基礎知識)。那么為什么要設計兩種結構體呢?先來看下IP和端口的定義。
            1)IP(Internet Protocol)
        為了使計算機連接到網絡并收發數據,必須向其分配IP地址。IP地址主要分為兩類:IPv4和IPv6。IPv4是4字節的,IPv6是為了應對IP地址耗盡的問題而提出的標準,它是16字節的。目前主要應用的還是IPv4,這里也只討論IPv4的情況。
        IPv4標準的4字節IP地址分為網絡地址和主機地址,且分為A、B、C、D、E等類型,E類作為保留使用,如圖一-3-1所示。
圖一-3-1
        數據在互聯網進行傳輸的時候,首先瀏覽網絡地址,將數據傳輸到對應的網絡,再由該網絡將數據分派到對應的主機。
        并且只需要判斷首字節就能清楚的知道是哪類地址。A類地址首字節范圍:0~127,B類地址首字節范圍:128~191,A類地址首字節范圍:192~223。
            2)端口號
        IP用于區分計算機,端口號用于區分應用程序。比如你在看視頻和瀏覽網頁的時候都需要用到數據傳輸,那么如何區分數據是傳遞到那個應用程序呢,就需要給套接字指定端口號。端口號是一個2字節的無符號整型,端口號范圍0-65535,其中0-1023為知名端口已經被占用(如FTP、HTTP、SMTP)。
            3)地址信息詳解
        了解IP和端口后,就可以填充sockaddr_in結構了。讓我們再來回顧一下sockaddr_in結構體。
                * sin_family
                        還記得創建socket時候的第一個參數嗎?我們這里只討論IPv4協議族,所以這里用PF_INET即可(有些代碼里用AF_INET,它和PF_INET在Windows里是同一個宏)。
                * sin_port
                        保存16位(2字節)端口號,需要以網絡字節序保存(稍后介紹)。
                * sin_addr
                        保存32位(4字節)IP地址信息,以網絡字節序保存。雖然是個結構體,但是結構體下只有一個整型變量,所以可以直接理解成32位整數即可。
                * sin_zero
                        保留字段,只是為了和sockaddr字節對齊。引入sockaddr_in的原因是當協議族不是PF_INET時,情況不一樣。比如IPv6的情況,IP地址是16個字節的,sin_addr明顯不夠用。
            4)主機字節序/網絡字節序
        主機字節序主要有兩種:大端序:高字節放低位地址、小端序:高字節放高位地址。
        例如,一個2字節的數字0x1234,存放的基地址為0x10。如果采用大端序,0x10存放0x12,0x11存放0x34。如果采用小端序,0x10存放0x34,0x11存放0x12。
        網絡傳輸數據時統一采用大端序。所以必須先將數據轉化成大端序格式再進行網絡傳輸。轉換函數操作系統已經給出了,總共有如下四個:htons、ntohs、htonl、ntohl。
        我去!這是什么鬼?
        不用擔心,其實這四個函數很容易識別,它是由h、to、n、l、s這幾個詞拼出來的。h代表host,n則是network,l是long,s是short。
        主要用于對IP和端口進行主機字節序和網絡字節序的轉換。那么也許有人會問,那實際數據傳輸的時候也需要這么干嗎?答案是否定的!
            5)綁定IP和端口
        實際綁定過程如下代碼所示:
                #define IP "156.123.122.11"
                #define PORT 10101
                struct sockaddr_in serv_addr;

                memset(&serv_addr, 0, sizeof(serv_addr));
                serv_addr.sin_family = PF_INET;
                serv_addr.sin_addr.s_addr = inet_addr(IP);
                serv_addr.sin_port = htons(PORT);
                bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        其中inet_addr是系統函數,將點分十進制的IP地址轉換成32位大端序的整型值,失敗返回 INADDR_NONE。
 二、基于TCP的服務器端
        1、TCP/IP協議
        根據數據傳輸方式的不同,基于網絡協議的套接字一般分為TCP套接字和UDP套接字。還記得創建套接字時指定的第二個參數嗎?當它為SOCK_STREAM時,即為TCP套接字。TCP是Transmission Control Protocol(傳輸控制協議)的簡稱。TCP和UDP處于網絡四層協議棧的傳輸層(網絡接口層-IP層-傳輸層-應用層)。之所以要分層,是為了通過標準化操作設計開放式系統,路由器用來完成IP層的交互任務,不同公司生產的路由器可以進行互相替換,因為生產商會按照IP層的標準制造。而網卡則是遵循了網絡接口層的協議標準制造的。
        2、TCP服務端主流程

圖二-2-1
        如圖二-2-1所示,為TCP服務端的函數調用順序。調用socket創建套接字,然后利用bind為套接字分配地址。利用listen使對應套接字進入等待連接請求狀態。如果有新的請求,則調用accept接收新的客戶端連接。接著使用read(接收)和write(發送)實現數據交換。數據交換完畢調用close關閉套接字。
        3、等待連接請求
        只有當服務端調用了listen函數等待連接請求,客戶端才有機會接入。listen的調用比較簡單。
                int listen(int sockfd, int backlog);
                          成功時返回0,失敗時返回-1。
        sockfd代表了希望進入等待連接請求的文件描述符,傳遞完畢后該套接字成為服務器端套接字(監聽套接字)。backlog為指定的連接請求等待隊列的長度。
        對于一個TCP連接,服務器端與客戶端需要通過三次握手來建立網絡連接。當三次握手成功后,端口狀態由LISTEN轉變為ESTABLISHED,接著這條鏈路上就可以開始傳送數據了。每一個處于監聽(Listen)狀態的端口,都有自己的監聽隊列。監聽隊列的長度與如下兩方面有關:
            a. proc/sys/net/core/somaxconn
            b. listen 的第二個參數backlog
        隊列大小為兩者的小值,可以通過 echo 1000 > proc/sys/net/core/somaxconn 來修改前者。第二個參數backlog設置太小會導致高并發情況下,客戶端connect的時候隊列滿了,服務器端就不會受理了,客戶端繼續嘗試...如果還是滿的...就這樣惡性循環,最后導致連接超時。
        4、受理請求
        服務端受理客戶端請求是由以下函數完成的:
                int accept(int sockfd, struct sockaddr* addr, socket_t* addrlen);
                          成功時返回創建的套接字文件描述符,失敗時返回-1。
        函數調用成功后,操作系統將產生用于數據I/O的套接字。當客戶端發起connect(稍后第三節會講到)請求,服務端不會馬上受理,而是將這些請求放在listen所對應套接字的等待隊列中,accept的作用就是將隊列首的請求取出來進行受理。accept的第二個參數addr就保存了客戶端的地址信息,因為調用前我們并不知道是哪個客戶端接入的,所以我們并不需要填充addr指向的結構。當accept返回時,自然就把地址填在*addr(注意前面的*,表示解引用,因為addr是個指針)了。
        并且如果沒有特殊指定,accept是同步阻塞的,即當等待隊列為空時,accept函數不會返回。
        5、數據交換
        所謂數據交換,就是我們通常所說的I/O(Input/Output)。對于TCP連接(UDP的先不介紹),主要有兩個系列的函數:
        a、read/write      (Linux)
        b、recv/send       (Windows/Linux)
        限于篇幅問題,這里簡單介紹下read和write,剩余內容待到日后再詳細研究。
                int read(int fd, void *buf, size_t nbytes);
                          成功時返回接收到的字節數(遇到文件結尾返回0),失敗時返回-1。
        read用于讀取(接收)數據。fd代表數據接收對象的文件描述符,可以是文件也可以是套接字;buf保存了接收數據的首地址;nbytes代表將要接收的最大字節數。
                int write(int fd, const void *buf, size_t nbytes);
                          成功時返回發送的字節數,失敗時返回-1。
        write用于寫入(發送)數據。fd代表數據發送對象的文件描述符,可以是文件也可以是套接字;buf傳入的是發送數據的首地址;nbytes代表發送的最大字節數。
        read和write相呼應,一端進行write,另一端進行read。這里涉及到I/O緩沖的問題,有必要解釋一下。對于TCP而言,數據收發無邊界,意味著服務端調用3次write函數,每次10字節(數據收發以字節為單位),客戶端有可能通過一次read調用直接接收30字節的數據,反之亦然。那么這個是如何做到的呢?發送出去的字節在沒有接收的情況下是寄存在哪里的?
        如圖二-5-1,write函數調用后并非立即發送數據,read函數調用后也并非立即接收數據。write調用瞬間,數據將移至輸出緩沖;read調用瞬間,從輸入緩沖讀取數據。并且在適當的時候,會將本地的輸出緩沖的數據傳送到對方的輸入緩沖中區。
圖二-5-1
        這里需要理清幾個知識點:
        a.每個TCP套接字都有自己的I/O緩沖,并且在創建該套接字時自動生成(即用戶不需要關心它的創建和銷毀)。
        b.如果輸出緩沖中還有數據,關閉套接字,這些數據還是會傳送出去。
        c.如果輸入緩沖中還有數據,關閉套接字,這些數據就丟失了。
        那么write函數何時返回?等到對方read之后才返回?答案是否定的。我們之前提到了輸出緩沖,沒錯,write函數就是負責將數據移動到輸出緩沖,然后就返回了。那么如果輸出緩沖滿了怎么辦?這個又是一個值得討論的問題。需要分阻塞socket和非阻塞socket,限于篇幅先不考慮,以后專門講這個問題。對于read的時候緩沖區為空時,同樣需要考慮阻塞和非阻塞的情況。
        6、關閉套接字
        直接給出關閉函數:
                int close(int sockfd);
                          成功時返回0,失敗時返回-1。
        關閉函數還有一個叫shutdown的,屬于“半關閉”。這里先介紹到這里。
        最后,附上只處理一個請求的服務端源碼:https://pan.baidu.com/s/1qXGuhB2
        7、調試工具
        這里假設我們的服務器是架設在Linux上的,可以利用gcc(GNU Compiler Collection)對源文件進行編譯和鏈接。
            gcc test.c -o test
                    將test.c預處理、匯編、編譯并鏈接形成可執行文件test。-o選項用來指定輸出文件的文件名。
            gcc -g test.c -o test
                    增加-g選項,便于用gdb進行調試。
        程序出現錯誤后,會生成一個core.test.30212的dump文件(其中30212為當時運行時候的進程ID),可以利用gdb進行堆棧查看。
            gdb test core.test.30212
        運行指令后,進入gdb調試界面。輸入where、backtrace、info stack都可以查看到發生錯誤的堆棧。
        注意:寫代碼的時候可以在核心代碼的前后打上printf用于測試代碼是否正確運行到這里,注意Linux下printf最后需要加上'\n',因為printf是行緩沖。
 三、基于TCP的客戶端
        1、TCP客戶端主流程
        客戶端的結構相對于服務端比較簡單,創建socket之后調用connect進行連接,剩下的流程就一樣了。
圖三-1-1
        2、請求連接
        請求連接的函數如下:
                int connect(int sockfd, struct sockaddr* servaddr, socket_t addrlen);
                          成功時返回0,失敗時返回-1。
        第一個參數為客戶端的文件描述符,第二個參數為服務端的網絡地址(同上文中的bind)的指針,第三個參數傳入sizeof(sockaddr)即可。
        上文說到服務端調用listen函數后創建連接請求的等待隊列,這時候客戶端調用connect進行請求。connect函數的返回條件是服務端接收連接請求或者發生斷網等異常情況,這里的服務端“接收連接“并不是代表服務端調用accept,其實服務端把請求記錄到等待隊列里。
        客戶端進行本次連接的IP和端口號并不需要應用程序去分配,操作系統已經把這點做好了。
        同樣附上一個簡單的客戶端連接源碼:https://pan.baidu.com/s/1nuRV8Zf

四、回顧主流程
        最后我們來回顧下,今天學到的主要內容。用偽代碼來描述下整個過程。
        服務端:
        int main() {
            server_sock = socket();
            bind(server_sock);
            listen(server_sock, 5);
            client_sock = accept(server_sock);
            read(client_sock, buf);
            write(client_sock, buf);
            close(client_sock);
            close(server_sock);
        }
        客戶端:
        int main() {
            sock = socket();
            connect(sock);
            write(sock, buf);
            read(sock, buf);
            close(sock);
        }
    
        (未完待續...)

posted on 2017-12-20 20:36 英雄哪里出來 閱讀(1506) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   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>
            亚洲成人资源| 欧美激情中文不卡| 欧美国产精品日韩| 久久久青草婷婷精品综合日韩| 欧美精品日韩| 欧美韩日精品| 在线看视频不卡| 欧美一区二区三区电影在线观看| 99精品国产在热久久下载| 久久一区二区三区四区| 久久久综合精品| 国产一区二区三区在线观看免费| 中文国产成人精品| 亚洲一卡久久| 欧美破处大片在线视频| 亚洲国产精品成人一区二区| 好看不卡的中文字幕| 先锋影音久久久| 久久国产精品久久久久久电车| 国产精品国产成人国产三级| 99国产精品自拍| 中文一区二区| 国产精品对白刺激久久久| 一本在线高清不卡dvd| 一区二区高清视频在线观看| 欧美伦理视频网站| 日韩视频不卡| 亚洲一区视频在线观看视频| 国产精品国产三级国产aⅴ入口| 99视频一区| 午夜视黄欧洲亚洲| 国产欧美日韩精品丝袜高跟鞋 | 欧美精品日韩一本| 91久久精品国产91久久| 夜夜爽99久久国产综合精品女不卡| 欧美成人一品| 日韩一级视频免费观看在线| 亚洲一区二区三区中文字幕在线| 国产精品盗摄一区二区三区| 亚洲摸下面视频| 久久久精品日韩| 亚洲电影有码| 欧美日韩极品在线观看一区| 亚洲香蕉在线观看| 久久免费视频观看| 亚洲精品三级| 国产精品一区二区欧美| 欧美中文字幕视频在线观看| 欧美国产日韩xxxxx| 正在播放亚洲一区| 国产一区二区三区久久| 免费成人黄色| 亚洲图片欧洲图片日韩av| 久久久久久久一区二区| 亚洲精品欧美日韩专区| 国产精品久久毛片a| 久久综合狠狠| 亚洲美女色禁图| 久久久夜色精品亚洲| 亚洲精品久久久久中文字幕欢迎你| 欧美日韩在线观看一区二区| 欧美一区二区在线免费观看| 亚洲国产成人在线播放| 香蕉视频成人在线观看| 亚洲国产电影| 国产欧美精品日韩精品| 欧美国产亚洲精品久久久8v| 午夜天堂精品久久久久| 亚洲激精日韩激精欧美精品| 性欧美在线看片a免费观看| 亚洲三级影院| 国产亚洲精品一区二555| 欧美精品v国产精品v日韩精品| 午夜精品久久久久久久男人的天堂 | 亚洲国产精品第一区二区| 欧美午夜视频在线| 美女黄毛**国产精品啪啪| 亚洲专区在线| 亚洲精品日韩在线观看| 麻豆九一精品爱看视频在线观看免费| 亚洲一二三区视频在线观看| 亚洲国产日韩欧美在线99 | 亚洲国内精品在线| 国产香蕉97碰碰久久人人| 欧美日韩亚洲一区二区三区| 免费观看国产成人| 久久国产黑丝| 香蕉亚洲视频| 亚洲欧美美女| 亚洲网站视频| 一区二区三区久久| 亚洲精品看片| 亚洲国内自拍| 亚洲国产精品va在线观看黑人| 久久久久久久久一区二区| 欧美一区亚洲二区| 午夜精品视频在线| 亚洲制服av| 亚洲免费一区二区| 亚洲午夜高清视频| 一区二区三区国产精品| 亚洲精品国产精品国自产观看| 一区二区在线观看视频在线观看| 国产欧美精品va在线观看| 国产精品日日摸夜夜添夜夜av| 欧美日韩日本视频| 欧美色大人视频| 欧美性片在线观看| 国产精品久久一卡二卡| 国产精品狠色婷| 国产精品久久久久久久9999| 国产精品99免费看 | 欧美成人一区二区| 免费久久99精品国产自在现线 | 午夜精品av| 性色av一区二区三区在线观看| 亚洲欧美不卡| 久久精品国产一区二区电影 | 日韩视频在线播放| 一本久道久久综合狠狠爱| 一本色道久久综合一区 | 美女啪啪无遮挡免费久久网站| 久久久久久久久久久久久女国产乱 | 亚洲午夜激情| 欧美在线免费| 免费观看成人网| 欧美日韩和欧美的一区二区| 欧美视频中文字幕在线| 国产精品视频专区| 国产综合色产在线精品| 在线观看视频一区二区欧美日韩| 在线欧美日韩国产| 一区二区久久久久久| 午夜亚洲影视| 欧美精品一卡二卡| 国产精品蜜臀在线观看| 午夜欧美电影在线观看| 亚洲欧美一区二区原创| 久久久噜噜噜久噜久久| 这里只有视频精品| 午夜伦欧美伦电影理论片| 久久女同互慰一区二区三区| 亚洲欧美久久久| 亚洲人体1000| 免费欧美日韩| 亚洲国产精品第一区二区三区 | 久久久99国产精品免费| 国产精品视频免费观看| 一区二区三区日韩在线观看 | 国产精品劲爆视频| 在线视频免费在线观看一区二区| 欧美电影免费观看| 久久久噜噜噜久久人人看| 国产一区二区电影在线观看| 欧美一区深夜视频| 亚洲自拍16p| 国产精品久久久久久av福利软件| 一二三区精品| 亚洲人成在线观看网站高清| 欧美激情第8页| 日韩午夜中文字幕| 亚洲美女免费精品视频在线观看| 欧美激情1区2区| aa成人免费视频| 亚洲卡通欧美制服中文| 欧美伦理91i| 亚洲一区二区三区午夜| 中文国产一区| 国产欧美一区二区三区在线老狼 | 亚洲无吗在线| 国产精品影音先锋| 久久精品论坛| 久久亚洲不卡| 亚洲久色影视| 一本不卡影院| 国产日本欧美在线观看| 久久中文精品| 牛夜精品久久久久久久99黑人 | 欧美承认网站| 亚洲视频在线二区| 午夜精品影院在线观看| 激情综合五月天| 亚洲国产一区二区三区a毛片| 欧美激情一区二区三区在线 | 久久成人精品一区二区三区| 欧美中在线观看| 亚洲国产一区二区a毛片| 亚洲精品欧美一区二区三区| 国产精品国码视频| 久久最新视频| 欧美日韩国产在线播放| 香蕉免费一区二区三区在线观看| 久久精品成人一区二区三区蜜臀| 亚洲国产日韩一区| 一本久道综合久久精品| 国产一区二区三区在线观看免费 | 久热国产精品视频| 欧美日韩国产页| 久久久在线视频| 欧美日韩国产精品一区二区亚洲|