3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux C/C++编程:setsockopt、getsockopt

發(fā)布時(shí)間:2024/3/12 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C/C++编程:setsockopt、getsockopt 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 概敘
    • 理論
    • 實(shí)踐:當(dāng)前系統(tǒng)支持哪些socket選項(xiàng)
  • 通用套接字選項(xiàng)
    • TCP_DEFER_ACCEPT
    • TCP_NODELAY
    • TCP_FASTOPEN
    • SO_REUSEADDR、SO_REUSEPORT
    • SO_ACCEPTCONN
    • SO_SNDBUF和SO_RCVBUF
      • 理論
        • 含義
        • 與實(shí)際使用內(nèi)存的關(guān)系?
        • 與滑動(dòng)窗口的關(guān)系?
          • 接收緩存區(qū)和接收滑動(dòng)窗口關(guān)系
          • 發(fā)送緩存區(qū)和發(fā)送滑動(dòng)窗口關(guān)系
        • 緩沖區(qū)大小預(yù)估
      • 1. 獲取接收緩沖區(qū)的大小
      • 2. 封裝
    • SO_RCVLOWAT、SO_SNDLOWAT
    • SO_BROADCAST套接字選項(xiàng)
    • SO_DEBUG 套接字選項(xiàng)
    • SO_DONTROUTE套接字選項(xiàng)
    • SO_ERROR套接字選項(xiàng)
    • SO_KEEPALIVE套接字選項(xiàng)
    • SO_LINGER
    • SO_ERROR
    • SO_RCVTIMEO, SO_SNDTIMEO
      • 示例1:設(shè)置connect超時(shí)時(shí)間
      • 示例2:超時(shí)接收(服務(wù)器數(shù)據(jù))

概敘

理論

如果說fcntl系統(tǒng)調(diào)用是控制文件描述符屬性的通用POSIX方法,那么setsockopt、getsockopt就是專門用來讀取和設(shè)置socket文件描述符屬性的方法

#include <sys/socket.h> /* * 參數(shù): sockfd: 指向一個(gè)打開的套接字描述符 * level: 指定系統(tǒng)中解釋選項(xiàng)的代碼或者通用套接字,或者指定要操作哪個(gè)協(xié)議的選項(xiàng)(比如IPV4,IPV6,TCP, SCTP) * optname:指定選項(xiàng)的名字 * optval、optlen:被操作選項(xiàng)的值和長度 * setsockopt從*optval中取得選項(xiàng)待設(shè)置的新值 * getsockopt則把已獲取的選項(xiàng)當(dāng)前值放到*optval中。 * 返回值: 成功0,出錯(cuò)-1并設(shè)置error */ int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen); int getsockopt(int socket, int level, int option_name,void *restrict optval, socklen_t *restrict option_len);

下面匯總了所有可以由setsockopt和getsockopt設(shè)置的選項(xiàng)。其中“數(shù)據(jù)類型”給出了指針optval必須指向的每個(gè)選項(xiàng)的數(shù)據(jù)類型,比如linger{}表示struct linger




實(shí)踐:當(dāng)前系統(tǒng)支持哪些socket選項(xiàng)

檢查上表選項(xiàng)是否得到支持,如果有,則輸出默認(rèn)值

#include <netinet/tcp.h> /* for TCP_xxx defines */ #include <stddef.h> #include <netinet/in.h> #include <stdio.h> #include <unp.h>//在Union類型中枚舉每一個(gè)getsockopt的每個(gè)可能的返回值 union val {int i_val;long l_val;struct linger linger_val;struct timeval timeval_val; } val;// 為用戶輸出給定套接字選項(xiàng)的4個(gè)函數(shù)定義原型 static char *sock_str_flag(union val *, int); static char *sock_str_int(union val *, int); static char *sock_str_linger(union val *, int); static char *sock_str_timeval(union val *, int);// sock_opts結(jié)構(gòu)包含給每個(gè)套接字選項(xiàng)調(diào)用getsockopt并輸出其當(dāng)前值所需要的信息 // sock_opts數(shù)組里面的每個(gè)元素代表一個(gè)套接字選項(xiàng) struct sock_opts {const char *opt_str;int opt_level;int opt_name;char *(*opt_val_str)(union val *, int); } sock_opts[] = {{ "SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag },{ "SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag },{ "SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, sock_str_flag },{ "SO_ERROR", SOL_SOCKET, SO_ERROR, sock_str_int },{ "SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, sock_str_flag },{ "SO_LINGER", SOL_SOCKET, SO_LINGER, sock_str_linger },{ "SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, sock_str_flag },{ "SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, sock_str_int },{ "SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, sock_str_int },{ "SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, sock_str_int },{ "SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, sock_str_int },{ "SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval },{ "SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval },{ "SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, sock_str_flag }, #ifdef SO_REUSEPORT{ "SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag }, #else{ "SO_REUSEPORT", 0, 0, NULL }, #endif{ "SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int },// { "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag },{ "IP_TOS", IPPROTO_IP, IP_TOS, sock_str_int },{ "IP_TTL", IPPROTO_IP, IP_TTL, sock_str_int }, #ifdef IPV6_DONTFRAG{ "IPV6_DONTFRAG", IPPROTO_IPV6,IPV6_DONTFRAG, sock_str_flag }, #else{ "IPV6_DONTFRAG", 0, 0, NULL }, #endif #ifdef IPV6_UNICAST_HOPS{ "IPV6_UNICAST_HOPS", IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int }, #else{ "IPV6_UNICAST_HOPS", 0, 0, NULL }, #endif #ifdef IPV6_V6ONLY{ "IPV6_V6ONLY", IPPROTO_IPV6,IPV6_V6ONLY, sock_str_flag }, #else{ "IPV6_V6ONLY", 0, 0, NULL }, #endif{ "TCP_MAXSEG", IPPROTO_TCP,TCP_MAXSEG, sock_str_int },{ "TCP_NODELAY", IPPROTO_TCP,TCP_NODELAY, sock_str_flag }, #ifdef SCTP_AUTOCLOSE{ "SCTP_AUTOCLOSE", IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int }, #else{ "SCTP_AUTOCLOSE", 0, 0, NULL }, #endif #ifdef SCTP_MAXBURST{ "SCTP_MAXBURST", IPPROTO_SCTP,SCTP_MAXBURST, sock_str_int }, #else{ "SCTP_MAXBURST", 0, 0, NULL }, #endif #ifdef SCTP_MAXSEG{ "SCTP_MAXSEG", IPPROTO_SCTP,SCTP_MAXSEG, sock_str_int }, #else{ "SCTP_MAXSEG", 0, 0, NULL }, #endif #ifdef SCTP_NODELAY{ "SCTP_NODELAY", IPPROTO_SCTP,SCTP_NODELAY, sock_str_flag }, #else{ "SCTP_NODELAY", 0, 0, NULL }, #endif{ NULL, 0, 0, NULL } }; /* *INDENT-ON* */ /* end checkopts1 *//* include checkopts2 */ int main(int argc, char **argv) {int fd;socklen_t len;struct sock_opts *ptr;for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {printf("%s: ", ptr->opt_str);if (ptr->opt_val_str == NULL)printf("(undefined)\n");else {switch(ptr->opt_level) {case SOL_SOCKET:case IPPROTO_IP:case IPPROTO_TCP:fd = Socket(AF_INET, SOCK_STREAM, 0);break; #ifdef IPV6case IPPROTO_IPV6:fd = Socket(AF_INET6, SOCK_STREAM, 0);break; #endif #ifdef IPPROTO_SCTPcase IPPROTO_SCTP:fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);break; #endifdefault:err_quit("Can't create fd for level %d\n", ptr->opt_level);}len = sizeof(val);if (getsockopt(fd, ptr->opt_level, ptr->opt_name,&val, &len) == -1) {err_ret("getsockopt error");} else {printf("default = %s\n", (*ptr->opt_val_str)(&val, len));}close(fd);}}exit(0); }static char strres[128];static char *sock_str_int(union val *ptr, int len) {if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres), "%d", ptr->i_val);return(strres); } static char *sock_str_flag(union val *ptr, int len) {if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres),"%s", (ptr->i_val == 0) ? "off" : "on");return(strres); } static char *sock_str_linger(union val *ptr, int len) {struct linger *lptr = &ptr->linger_val;if (len != sizeof(struct linger))snprintf(strres, sizeof(strres),"size (%d) not sizeof(struct linger)", len);elsesnprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d",lptr->l_onoff, lptr->l_linger);return(strres); }static char *sock_str_timeval(union val *ptr, int len) {struct timeval *tvptr = &ptr->timeval_val;if (len != sizeof(struct timeval))snprintf(strres, sizeof(strres),"size (%d) not sizeof(struct timeval)", len);elsesnprintf(strres, sizeof(strres), "%d sec, %d usec",tvptr->tv_sec, tvptr->tv_usec);return(strres); }

通用套接字選項(xiàng)

TCP_DEFER_ACCEPT

Linux 提供的一個(gè)特殊 setsockopt , 在 accept 的 socket 上面,只有當(dāng)實(shí)際收到了數(shù)據(jù),才喚醒正在 accept 的進(jìn)程,可以減少一些無聊的上下文切換

  • 經(jīng)過測試發(fā)現(xiàn),設(shè)置TCP_DEFER_ACCEPT選項(xiàng)后,服務(wù)器受到一個(gè)CONNECT請(qǐng)求后,操作系統(tǒng)不會(huì)Accept,也不會(huì)創(chuàng)建IO句柄。操作系統(tǒng)應(yīng)該在若干秒,(但肯定遠(yuǎn)遠(yuǎn)大于上面設(shè)置的1s) 后,會(huì)釋放相關(guān)的鏈接。但沒有同時(shí)關(guān)閉相應(yīng)的端口,所以客戶端會(huì)一直以為處于鏈接狀態(tài)。如果Connect后面馬上有后續(xù)的發(fā)送數(shù)據(jù),那么服務(wù)器會(huì)調(diào)用Accept接收這個(gè)鏈接端口。
  • 感覺了一下,這個(gè)端口設(shè)置對(duì)于CONNECT鏈接上來而又什么都不干的攻擊方式處理很有效。我們?cè)瓉淼拇a都是先允許鏈接,然后再進(jìn)行超時(shí)處理,比他這個(gè)有點(diǎn)Out了。不過這個(gè)選項(xiàng)可能會(huì)導(dǎo)致定位某些問題麻煩。
/*** 設(shè)置監(jiān)聽套接字的延遲接收功能,即當(dāng)客戶端連接上有數(shù)據(jù)時(shí)才將該連接返回* 給應(yīng)用,目前該功能僅支持 Linux* @param fd {ACL_SOCKET} 套接字* @param timeout {int} 如果客戶端連接在規(guī)定的時(shí)間內(nèi)未發(fā)來數(shù)據(jù),也將該連接返回* 給應(yīng)用*/void acl_tcp_defer_accept(ACL_SOCKET fd, int timeout){ #ifdef TCP_DEFER_ACCEPTif (timeout < 0)timeout = 0;if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,&timeout, sizeof(timeout)) < 0){acl_msg_error("%s: setsockopt(TCP_DEFER_ACCEPT): %s",__FUNCTION__ , strerror(errno));} #endif}

可以通過setsockopt來設(shè)置defer accept:setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(timeout)) < 0

  • 其中,timeout為超時(shí)時(shí)間,內(nèi)核會(huì)把此時(shí)間轉(zhuǎn)換為最大重傳次數(shù)。
  • 單位是秒,注意如果打開這個(gè)功能,kernel 在 val 秒之內(nèi)還沒有收到數(shù)據(jù),不會(huì)繼續(xù)喚醒進(jìn)程,而是直接丟棄連接。

在不使用此選項(xiàng)的情況下,TCP三次握手建立連接的過程為:

  • Client -> Server:SYN
  • Server -> Client: SYN + ACK,Server端的連接為SYN_RECV狀態(tài)
  • Client -> Server: ACK,Client和Server端的連接均為ESTABLISHED
    • 使用此選項(xiàng)時(shí),若Client和Server完成三次握手,
    • 但Client并沒有數(shù)據(jù)發(fā)來,這時(shí)Server并不會(huì)把連接的狀態(tài)置為ESTABLISHED,而是會(huì)忽略最后一次ACK,保持SYN_RECV狀態(tài)不變,應(yīng)用也就沒有機(jī)會(huì)accept這個(gè)連接,
    • 這樣可以避免Client建立連接卻不發(fā)送請(qǐng)求,導(dǎo)致Server的資源浪費(fèi),
    • 尤其對(duì)于像Apache這樣的應(yīng)用,接收到連接之后會(huì)一直阻塞等待Client的請(qǐng)求數(shù)據(jù),直到超時(shí),嚴(yán)重影響服務(wù)的性能和穩(wěn)定性。

    然,不同的內(nèi)核版本對(duì)此選項(xiàng)的支持卻大不一樣,比如 2.6.18 和 2.6.32的行為就大不相同,對(duì)比內(nèi)核源碼:

  • 三次握手完成后,判斷是否丟棄后續(xù)重傳的ACK的條件不一樣
    • 2.6.18:丟棄ack的條件是設(shè)置了defer accept選項(xiàng):
    • 2.6.32:丟棄ack的條件是重傳ack的次數(shù)小于在設(shè)置defer accept時(shí)指定的值(內(nèi)核會(huì)根據(jù)timeout參數(shù)的值計(jì)算最大重傳次數(shù)):
  • 三次握手完成后,若一直沒有請(qǐng)求數(shù)據(jù)到來,重傳行為不一樣
    • 2.6.18:重傳SYN+ACK,若Client及時(shí)響應(yīng)ACK但沒有數(shù)據(jù)到來,Server就會(huì)定時(shí)重傳SYN+ACK,保持連接狀態(tài)SYN_RECV不變。
    • 2.6.32:實(shí)際上并不會(huì)多次重傳SYN+ACK,雖然中間會(huì)定時(shí)計(jì)算是否需要重傳,但只會(huì)重傳超時(shí)時(shí)間之內(nèi)的最后一次SYN+ACK,看下面代碼,注意注釋:
  • 三次握手完成后,若一直沒有請(qǐng)求數(shù)據(jù)到來,Accept行為不一樣
    • 2.6.18:由于Server端連接狀態(tài)保持為SYN_RECV,超過最大重傳次數(shù)后,Server會(huì)刪掉SYN_RECV狀態(tài)的連接,應(yīng)用也就沒有機(jī)會(huì)Accept這個(gè)新連接。Client看到的狀態(tài)仍然是ESTABLISHED,但此連接并沒有占用Server的資源。
    • 2.6.32:若Client響應(yīng)最后一次重傳的SYN+ACK,由于中間會(huì)定時(shí)計(jì)算是否需要重傳并對(duì)重傳次數(shù)計(jì)數(shù)(req->restrans++),因此上面代碼中丟棄ACK的條件就不成立,Server就會(huì)把連接置為ESTABLISHED,交給應(yīng)用Accept這個(gè)新連接準(zhǔn)備讀取數(shù)據(jù)。下面的代碼顯示雖然中間不重傳SYN+ACK,但仍然計(jì)數(shù):

      結(jié)論:
      • 2.6.18內(nèi)核:若三次握手完成后Client沒有數(shù)據(jù)發(fā)來,Server的連接狀態(tài)一直是SYN_RECV,不會(huì)Accept新連接,直到把SYN_RECN狀態(tài)的連接刪除,但Client仍然顯示ESTABLISHED。
      • 2.6.32內(nèi)核:若三次握手完成后Client沒有數(shù)據(jù)發(fā)來,Server的連接狀態(tài)最終會(huì)變成ESTABLISHED,會(huì)Accept新連接,Client和Server連接的狀態(tài)均為ESTABLISHED。

    至于2.6.18之后從哪個(gè)版本開始變成了2.6.32的行為,沒有考證,2.6.32及之后的版本都是同樣的處理方式。

    此外,當(dāng)三次握手完成,且沒有數(shù)據(jù)到來,Server的連接狀態(tài)處于SYN_RECV狀態(tài)時(shí),如果Client發(fā)送FIN,則Server會(huì)響應(yīng)ack及后續(xù)的FIN,正常終止連接;在2.6.18上,若Server端已超時(shí),SYN_RECV狀態(tài)的連接被移除后,Client發(fā)送FIN時(shí),Server響應(yīng)RST。

    相關(guān)參數(shù):

  • net.ipv4.tcp_synack_retries:重傳SYN+ACK的次數(shù)
  • net.ipv4.tcp_syn_retries:重傳SYN的次數(shù)
  • setsockopt中的timeout:超時(shí)時(shí)間,計(jì)算時(shí)在這幾個(gè)參數(shù)中具有高優(yōu)先級(jí)
  • TCP_NODELAY

    糊涂窗口綜合征:是指當(dāng)發(fā)送端應(yīng)用進(jìn)程產(chǎn)生數(shù)據(jù)很慢、或接收端應(yīng)用進(jìn)程處理接收緩沖區(qū)數(shù)據(jù)很慢,或二者兼而有之;就會(huì)使應(yīng)用進(jìn)程間傳送的報(bào)文段很小,特別是有效載荷很小; 極端情況下,有效載荷可能只有1個(gè)字節(jié);傳輸開銷有40字節(jié)(20字節(jié)的IP頭+20字節(jié)的TCP頭) 這種現(xiàn)象。

    如果發(fā)送端為產(chǎn)生數(shù)據(jù)很慢的應(yīng)用程序服務(wù)(典型的有telnet應(yīng)用),例如,一次產(chǎn)生一個(gè)字節(jié)。這個(gè)應(yīng)用程序一次將一個(gè)字節(jié)的數(shù)據(jù)寫入發(fā)送端的TCP的緩存。如果發(fā)送端的TCP沒有特定的指令,它就產(chǎn)生只包括一個(gè)字節(jié)數(shù)據(jù)的報(bào)文段。結(jié)果有很多41字節(jié)的IP數(shù)據(jù)報(bào)就在互連網(wǎng)中傳來傳去。

    解決的方法是防止發(fā)送端的TCP逐個(gè)字節(jié)地發(fā)送數(shù)據(jù)。必須強(qiáng)迫發(fā)送端的TCP收集數(shù)據(jù),然后用一個(gè)更大的數(shù)據(jù)塊來發(fā)送。發(fā)送端的TCP要等待多長時(shí)間呢?如果它等待過長,它就會(huì)使整個(gè)的過程產(chǎn)生較長的時(shí)延。如果它的等待時(shí)間不夠長,它就可能發(fā)送較小的報(bào)文段。Nagle找到了一個(gè)很好的解決方法,發(fā)明了Nagle算法。

    用TCP_NODELAY選項(xiàng)可以禁止Negale 算法.

    #include <stdio.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <netinet/tcp.h> #include <rpc/types.h># define ACL_SOCKET int # define ACL_SOCKET_INVALID (int) -1 #define error printf #include <sys/un.h>typedef union {struct sockaddr_storage ss;struct sockaddr_in6 in6;struct sockaddr_in in;struct sockaddr_un un;struct sockaddr sa; } ACL_SOCKADDR;int main() {return 0; }/*** 取得套接字的類型:是網(wǎng)絡(luò)套接字還是域套接字* @param fd {ACL_SOCKET} 網(wǎng)絡(luò)套接字* @return {int} -1: 表示出錯(cuò)或輸入非法或非套接字; >= 0 表示成功獲得套接字* 類型,返回值有 AF_INET、AF_INET6 或 AF_UNIX*/ int acl_getsocktype(ACL_SOCKET fd) {ACL_SOCKADDR addr;struct sockaddr *sa = (struct sockaddr*) &addr;socklen_t len = sizeof(addr);if (fd == ACL_SOCKET_INVALID) {return -1;}if (getsockname(fd, sa, &len) == -1) {return -1;}if (sa->sa_family == AF_UNIX) {return AF_UNIX;}if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) {return sa->sa_family;}return -1; } /*** 設(shè)置 TCP 套接字的 nodelay 功能* @param fd {ACL_SOCKET} 套接字* @param onoff {int} 1 表示打開,0 表示關(guān)閉*/ void acl_tcp_nodelay(ACL_SOCKET fd, int onoff){const char *myname = "acl_tcp_nodelay";int on = onoff ? 1 : 0;int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return;if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,(char *) &on, sizeof(on)) < 0) {error("%s(%d): set nodelay error(%s), onoff(%d)",myname, __LINE__, strerror(errno), onoff);} }/*** 獲得 TCP 套接字是否設(shè)置了 nodelay 選項(xiàng)* @param fd {ACL_SOCKET} 套接字* @return {int} 1 表示打開,0 表示關(guān)閉*/ int acl_get_tcp_nodelay(ACL_SOCKET fd) {const char *myname = "acl_get_tcp_nodelay";socklen_t len;int on = 0;int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return 0;len = (socklen_t) sizeof(on);if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*) &on, &len) < 0) {error("%s(%d): getsockopt error: %s, fd: %d",myname, __LINE__, strerror(errno), fd);return -1;}return on; } /*** 打開 TCP 套接字的 nodelay 功能* @param fd {ACL_SOCKET} 套接字*/ void acl_tcp_set_nodelay(ACL_SOCKET fd) {acl_tcp_nodelay(fd, 1); }

    TCP_FASTOPEN

    TCP建立連接需要三次握手,這個(gè)大家都知道。但是三次握手會(huì)導(dǎo)致傳輸效率下降,尤其是HTTP這種短連接的協(xié)議,雖然HTTP有keep-alive來讓一些請(qǐng)求頻繁的HTTP提高性能,避免了一些三次握手的次數(shù),但是還是希望能繞過三次握手提高效率,或者說在三次握手的同時(shí)就把數(shù)據(jù)傳輸?shù)氖虑榻o做了。TCP Fast Open(簡稱TFO)就是來干這樣的事情的

    首先我們回顧一下三次握手的過程:

    這里客戶端在最后ACK的時(shí)候,完全可以將想要發(fā)送的第一條數(shù)據(jù)也一起帶過去,這是TFO做的其中一個(gè)優(yōu)化方案。

    然后TFO還參考了HTTP登錄態(tài)的流程,采用cookie的方案,讓客戶知道某個(gè)客戶端之前已經(jīng)登陸過了,那么它發(fā)過來的數(shù)據(jù)就可以直接接收了,不需要一開始必須三次握手再發(fā)送數(shù)據(jù)

    當(dāng)客戶端第一次連接服務(wù)端時(shí),是沒有Cookie的,所以會(huì)發(fā)送一個(gè)空的Cookie,意味著要請(qǐng)求Cookie,如下圖:

    這樣服務(wù)端就會(huì)將Cookie通過SYN+ACK的路徑返回給客戶端,客戶端保存后,將發(fā)送的數(shù)據(jù)三次握手的最后一步ACK同時(shí)發(fā)送給服務(wù)端。
    當(dāng)客戶端斷開連接,下一次請(qǐng)求同一個(gè)服務(wù)端的時(shí)候,會(huì)帶上之前存儲(chǔ)的Cookie和要發(fā)送的數(shù)據(jù),在SYN的路徑上一起發(fā)送給服務(wù)端,如下圖:

    這樣之后每次握手的時(shí)候還同時(shí)發(fā)送了數(shù)據(jù)信息,將數(shù)據(jù)傳輸提前了。服務(wù)端只要驗(yàn)證了Cookie,就會(huì)將發(fā)送的數(shù)據(jù)接收,否則會(huì)丟棄并且再通過SYN+ACK路徑返回一個(gè)新的Cookie,這種情況一般是Cookie過期導(dǎo)致的。

    TFO是需要開啟的,開啟參數(shù)在:

    /proc/sys/net/ipv4/tcp_fastopen 0:關(guān)閉 1:作為客戶端使用Fast Open功能,默認(rèn)值 2:作為服務(wù)端使用Fast Open功能 3:無論是客戶端還是服務(wù)端都使用Fast Open功能

    并且如果之前的代碼沒有做這方面的處理,也是不能使用的,從上面的流程圖就能看到,客戶端是在連接的過程就發(fā)送數(shù)據(jù),但是之前客戶端都是先調(diào)用connect成功后,才用send發(fā)送數(shù)據(jù)的。

    服務(wù)端需要對(duì)listen的socket設(shè)置如下選項(xiàng):

    //需要的頭文件 #include <netinet/tcp.h>int qlen = 5; //fast open 隊(duì)列 setsockopt(m_listen_socket, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));

    客戶端則直接使用sendto方法進(jìn)行連接和發(fā)送數(shù)據(jù),示例代碼如下:

    #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <unistd.h>int main(){struct sockaddr_in serv_addr;struct hostent *server;const char *data = "Hello, tcp fast open";int data_len = strlen(data); int sfd = socket(AF_INET, SOCK_STREAM, 0);server = gethostbyname("10.104.1.149");bzero((char *) &serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,server->h_length);serv_addr.sin_port = htons(5556);int len = sendto(sfd, data, data_len, MSG_FASTOPEN/*MSG_FASTOPEN*/, (struct sockaddr *) &serv_addr, sizeof(serv_addr));if(errno != 0){printf("error: %s\n", strerror(errno));}char buf[100] = {0};recv(sfd, buf, 100, 0);printf("%s\n", buf);close(sfd);}

    經(jīng)過試驗(yàn),客戶端存儲(chǔ)的Cookie是跟服務(wù)端的IP綁定的,而不是跟進(jìn)程或端口綁定。當(dāng)客戶端程序發(fā)送到同一個(gè)IP但是不同端口的進(jìn)程時(shí),使用的是同一個(gè)Cookie,而且服務(wù)端也認(rèn)證成功。

    SO_REUSEADDR、SO_REUSEPORT

    1、SO_REUSEADDR重用處于TIME_WAIT的socket

    • SO_REUSEADDR用于對(duì)TCP套接字處于TIME_WAIT狀態(tài)下的socket,才可以重復(fù)綁定使用。server程序總是應(yīng)該在調(diào)用bind()之前設(shè)置SO_REUSEADDR套接字選項(xiàng)。TCP,先調(diào)用close()的一方會(huì)進(jìn)入TIME_WAIT狀態(tài)
    • 另外一個(gè)方法:通過修改內(nèi)核參數(shù)/proc/sys/net/ipv4/tcp_tw_recycle來快速回收被關(guān)閉的socket,從而使得TCP連接根據(jù)不進(jìn)入TIME_WAIT狀態(tài),進(jìn)而運(yùn)行應(yīng)用程序立即重用本地的socket地址

    SO_REUSEADDR提供如下四個(gè)功能:

    • SO_REUSEADDR允許啟動(dòng)一個(gè)監(jiān)聽服務(wù)器并捆綁其眾所周知的端口,即使以前建立的將此端口用作他們的本地端口的連接仍舊存在。這通常是重啟監(jiān)聽服務(wù)器時(shí)出現(xiàn),如果不設(shè)置此項(xiàng),則bind出錯(cuò)
    • 假如一個(gè)systemd托管的service異常退出了,留下了TIME_WAIT狀態(tài)的socket,那么systemd將會(huì)嘗試重啟這個(gè)service。但是因?yàn)槎丝诒徽加?#xff0c;會(huì)導(dǎo)致啟動(dòng)失敗,造成兩分鐘的服務(wù)空檔期,systemd也可能在這期間放棄重啟服務(wù)
    • 但是在設(shè)置了SO_REUSEADDR以后,處于TIME_WAIT狀態(tài)的地址也可以被綁定,就杜絕了這個(gè)問題。因?yàn)門IME_WAIT其實(shí)本身就是半死狀態(tài),雖然這樣重用TIME_WAIT可能會(huì)造成不可預(yù)料的副作用,但是在現(xiàn)實(shí)中問題很少發(fā)生,所以也忽略了它的副作用。
    • SO_REUSEADDR允許在同一端口上啟動(dòng)同一服務(wù)器的多個(gè)實(shí)例,只要每個(gè)實(shí)例捆綁一個(gè)不同的本地IP地址即可。對(duì)于TCP,我們根本不可能啟動(dòng)捆綁相同IP地址和相同端口號(hào)的多個(gè)服務(wù)器。
    • SO_REUSEADDR允許單個(gè)進(jìn)程捆綁在同一端口的多個(gè)套接字上,只要每個(gè)捆綁指定不同的本地IP地址即可。這一般不用于TCP服務(wù)器。
    • SO_REUSEADDR允許完全重復(fù)的捆綁:當(dāng)一個(gè)IP地址和端口綁定到某個(gè)套接口上時(shí),還允許此IP地址和端口捆綁到另一個(gè)套接口上。一般來說,這個(gè)特性僅在支持多播的系統(tǒng)上才有,而且只對(duì)UDP套接口而言(TCP不支持多播)

    2、SO_REUSEPORT端口重用

    Linux kernel 3.9之前的版本,一個(gè)ip+port組合,只能被監(jiān)聽bind一次。這樣在多核環(huán)境下,往往只能有一個(gè)線程(或者進(jìn)程)是listener,在高并發(fā)情況下,往往這就是性能瓶頸。于是Linux kernel 3.9之后,Linux推出了端口重用SO_REUSEPORT選項(xiàng)。

    SO_REUSEPORT支持多個(gè)進(jìn)程或者線程綁定到同一端口,提高服務(wù)器程序的性能,解決的問題:

    • 允許多個(gè)套接字 bind()/listen() 同一個(gè)TCP/UDP端口

      • 每一個(gè)線程擁有自己的服務(wù)器套接字
      • 在服務(wù)器套接字上沒有了鎖的競爭
    • 內(nèi)核層面實(shí)現(xiàn)負(fù)載均衡

    • 安全層面,監(jiān)聽同一個(gè)端口的套接字只能位于同一個(gè)用戶下面

    其核心的實(shí)現(xiàn)主要有三點(diǎn):

    • 擴(kuò)展 socket option,增加 SO_REUSEPORT 選項(xiàng),用來設(shè)置 reuseport。
    • 修改 bind 系統(tǒng)調(diào)用實(shí)現(xiàn),以便支持可以綁定到相同的 IP 和端口
    • 修改處理新建連接的實(shí)現(xiàn),查找 listener 的時(shí)候,能夠支持在監(jiān)聽相同 IP 和端口的多個(gè) sock 之間均衡選擇。

    有了SO_RESUEPORT后,每個(gè)進(jìn)程可以自己創(chuàng)建socket、bind、listen、accept相同的地址和端口,各自是獨(dú)立平等的。讓多進(jìn)程監(jiān)聽同一個(gè)端口,各個(gè)進(jìn)程中accept socket fd不一樣,有新連接建立時(shí),內(nèi)核只會(huì)喚醒一個(gè)進(jìn)程來accept,并且保證喚醒的均衡性。

    4、使用這兩個(gè)套接字選項(xiàng)的定義

    • 在所有的TCP服務(wù)器上,在調(diào)用bind之前設(shè)置SO_REUSEADDR選項(xiàng)
    • 當(dāng)編寫一個(gè)同一時(shí)刻在同一主機(jī)上可運(yùn)行多次的多播應(yīng)用程序時(shí),設(shè)置SO_REUSEADDR選項(xiàng),并將本組的多播地址作為本地IP地址捆綁。

    SO_REUSEADDR選項(xiàng)的本質(zhì)?

    這個(gè)套接字選項(xiàng)通知內(nèi)核:

    • 如果端口忙,但是TCP狀態(tài)位于TIME_WAIT ,可以重用端口。
    • 如果端口忙,而TCP狀態(tài)位于其他狀態(tài),重用端口時(shí)依舊得到一個(gè)錯(cuò)誤信息,指明"地址已經(jīng)使用中"。

    一個(gè)套接字由相關(guān)五元組構(gòu)成,協(xié)議、本地地址、本地端口、遠(yuǎn)程地址、遠(yuǎn)程端口。SO_REUSEADDR 僅僅表示可以重用本地本地地址、本地端口,整個(gè)相關(guān)五元組還是唯一確定的。所以,重啟后的服務(wù)程序有可能收到非期望數(shù)據(jù)。必須慎重使用SO_REUSEADDR 選項(xiàng)。

    SO_REUSEPORT和SO_REUSEADDR

    從字面意思理解,SO_REUSEPORT是端口重用,SO_REUSEADDR是地址重用。兩者的區(qū)別:

    (1)SO_REUSEPORT是允許多個(gè)socket綁定到同一個(gè)ip+port上。SO_REUSEADDR用于對(duì)TCP套接字處于TIME_WAIT狀態(tài)下的socket,才可以重復(fù)綁定使用。

    (2)兩者使用場景完全不同。SO_REUSEADDR這個(gè)套接字選項(xiàng)通知內(nèi)核,如果端口忙,但TCP狀態(tài)位于TIME_WAIT,可以重用端口。這個(gè)一般用于當(dāng)你的程序停止后想立即重啟的時(shí)候,如果沒有設(shè)定這個(gè)選項(xiàng),會(huì)報(bào)錯(cuò)EADDRINUSE,需要等到TIME_WAIT結(jié)束才能重新綁定到同一個(gè)ip+port上。而SO_REUSEPORT用于多核環(huán)境下,允許多個(gè)線程或者進(jìn)程綁定和監(jiān)聽同一個(gè)ip+port,無論UDP、TCP(以及TCP是什么狀態(tài))。

    (3)對(duì)于多播,兩者意義相同。

    為什么要引入SO_REUSEPORT:

    1、驚群效應(yīng):簡單來說就是多個(gè)進(jìn)程或者線程等待同一個(gè)事件,當(dāng)事件發(fā)生時(shí),所有進(jìn)程和線程都會(huì)被內(nèi)核喚醒。喚醒之后通常只有一個(gè)進(jìn)程獲得了該事件并進(jìn)行處理,其他進(jìn)程發(fā)現(xiàn)獲取事件失敗之后又繼續(xù)進(jìn)入了等待狀態(tài),在一定長度上降低了性能。

    2、為什么驚群效應(yīng)會(huì)降低系列性能?

    • 多線程/多進(jìn)程的喚醒,會(huì)進(jìn)行上下文切換。頻繁的上下文切換帶來的一個(gè)問題是數(shù)據(jù)將頻繁的在寄存器與運(yùn)行隊(duì)列中流轉(zhuǎn)。極端情況下,時(shí)間更多的小號(hào)在進(jìn)程/線程的調(diào)度上,而不是執(zhí)行
    • 為了確保只有一個(gè)線程得到資源,用戶必須對(duì)資源操作進(jìn)行加鎖保護(hù),進(jìn)一步加大了系統(tǒng)開銷。

    3、常見的驚群問題
    在 Linux 下,我們常見的驚群效應(yīng)發(fā)生于我們使用 accept 以及我們 select 、poll 或 epoll 等系統(tǒng)提供的 API 來處理我們的網(wǎng)絡(luò)鏈接。

    (1) accept 驚群:

    首先我們用一個(gè)流程圖來復(fù)習(xí)下我們傳統(tǒng)的 accept 使用方式

    服務(wù)器

    #include <arpa/inet.h> #include <assert.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h>#define SERVER_ADDRESS "0.0.0.0" #define SERVER_PORT 10086 #define WORKER_COUNT 4int worker_process(int listenfd, int i) {while (1) {printf("I am work %d, my pid is %d, begin to accept connections \n", i,getpid());struct sockaddr_in client_info;socklen_t client_info_len = sizeof(client_info);int connection =accept(listenfd, (struct sockaddr *)&client_info, &client_info_len);if (connection != -1) {printf("worker %d accept success\n", i);printf("ip :%s\t", inet_ntoa(client_info.sin_addr));printf("port: %d \n", client_info.sin_port);} else {printf("worker %d accept failed", i);}close(connection);}return 0; }int main() {int i = 0;struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, SERVER_ADDRESS, &address.sin_addr);address.sin_port = htons(SERVER_PORT);int listenfd = socket(PF_INET, SOCK_STREAM, 0);int ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));ret = listen(listenfd, 5);for (i = 0; i < WORKER_COUNT; i++) {printf("Create worker %d\n", i + 1);pid_t pid = fork();/*child process */if (pid == 0) {worker_process(listenfd, i);}if (pid < 0) {printf("fork error");}}/*wait child process*/int status;wait(&status);return 0; }

    客戶端

    #include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include<arpa/inet.h> #include <unistd.h> #include <errno.h> #define SA struct sockaddr#define SERV_PORT 10086 int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr;sockfd = socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);connect(sockfd, (SA *) &servaddr, sizeof(servaddr));exit(0); }

    為什么這里沒有出現(xiàn)我們想要的現(xiàn)象(一個(gè)進(jìn)程 accept 成功,三個(gè)進(jìn)程 accept 失敗)?原因在于在 Linux 2.6 之后,Accept 的驚群問題從內(nèi)核上被處理了

    (2) select/poll/epoll 驚群:

    我們以 epoll 為例,我們來看看傳統(tǒng)的工作模式

    服務(wù)器:

    #include <errno.h> #include <fcntl.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/epoll.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h>#define SERVER_ADDRESS "0.0.0.0" #define SERVER_PORT 10086 #define WORKER_COUNT 4 #define MAXEVENTS 64static int create_and_bind_socket() {int fd = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in server_address;server_address.sin_family = AF_INET;inet_pton(AF_INET, SERVER_ADDRESS, &server_address.sin_addr);server_address.sin_port = htons(SERVER_PORT);bind(fd, (struct sockaddr *)&server_address, sizeof(server_address));return fd; }static int make_non_blocking_socket(int sfd) {int flags, s;flags = fcntl(sfd, F_GETFL, 0);if (flags == -1) {perror("fcntl error");return -1;}flags |= O_NONBLOCK;s = fcntl(sfd, F_SETFL, flags);if (s == -1) {perror("fcntl set error");return -1;}return 0; }int worker_process(int listenfd, int epoll_fd, struct epoll_event *events,int k) {while (1) {int n, i;n = epoll_wait(epoll_fd, events, MAXEVENTS, -1);printf("Worker %d pid is %d get value from epoll_wait\n", k, getpid());for (i = 0; i < n; i++) {if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) ||(!(events[i].events & EPOLLIN))) {printf("%d\n", i);fprintf(stderr, "epoll err\n");close(events[i].data.fd);continue;} else if (listenfd == events[i].data.fd) {struct sockaddr in_addr;socklen_t in_len;int in_fd;in_len = sizeof(in_addr);in_fd = accept(listenfd, &in_addr, &in_len);if (in_fd == -1) {printf("worker %d accept failed\n", k);break;}printf("worker %d accept success\n", k);close(in_fd);}}}return 0; }int main() {int listen_fd, s, i;int epoll_fd;struct epoll_event event;struct epoll_event *events;listen_fd = create_and_bind_socket();if (listen_fd == -1) {abort();}s = make_non_blocking_socket(listen_fd);if (s == -1) {abort();}s = listen(listen_fd, SOMAXCONN);if (s == -1) {abort();}epoll_fd = epoll_create(MAXEVENTS);if (epoll_fd == -1) {abort();}event.data.fd = listen_fd;event.events = EPOLLIN;s = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event);if (s == -1) {abort();}events = calloc(MAXEVENTS, sizeof(event));for ( i = 0; i < WORKER_COUNT; i++) {printf("create worker %d\n", i);int pid = fork();if (pid == 0) {worker_process(listen_fd, epoll_fd, events, i);}}int status;wait(&status);free(events);close(listen_fd);return EXIT_SUCCESS; }

    客戶端同上

    怎么使用?

    1、封裝

    # define ACL_SOCKET int # define ACL_SOCKET_INVALID (int) -1 ACL_SOCKET acl_inet_bind(const struct addrinfo *res, unsigned flag){ACL_SOCKET fd;int on;fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);if (fd == ACL_SOCKET_INVALID) {acl_msg_error("%s(%d): create socket %s",__FILE__, __LINE__, acl_last_serror());return ACL_SOCKET_INVALID;}on = 1;if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const void *) &on, sizeof(on)) < 0) {acl_msg_warn("%s(%d): setsockopt(SO_REUSEADDR): %s",__FILE__, __LINE__, acl_last_serror());}on = 1;if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,(const void *) &on, sizeof(on)) < 0)acl_msg_warn("%s(%d): setsocket(SO_REUSEPORT): %s",__FILE__, __LINE__, acl_last_serror());if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {close(fd);acl_msg_error("%s(%d): bind error %s",__FILE__, __LINE__, acl_last_serror());return ACL_SOCKET_INVALID;}return fd; }

    2、udp_reuseport_server/client

    參考

    SO_ACCEPTCONN

    • SO_ACCEPTCONN: 該套接字是否是監(jiān)聽套接字(listen)
    #include <sys/socket.h> /*** 檢查套接字:是監(jiān)聽套接字還是網(wǎng)絡(luò)套接字(已連接套接字)* @param fd {ACL_SOCKET} 套接字句柄* @return {int} 返回 -1 表示該句柄非套接字,1 為監(jiān)聽套接字,0 為非監(jiān)聽套接字*/ # define ACL_SOCKET int int acl_check_socket(ACL_SOCKET fd) {int val, ret;socklen_t len = sizeof(val);ret = getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, (void*) &val, &len);if (ret == -1) {return -1;} else if (val) {return 1;} else {return 0;} }/*** 判斷套接字是否為監(jiān)聽套接字* @param fd {ACL_SOCKET} 套接字句柄* @return {int} 返回值 0 表示非監(jiān)聽套接字,非 0 表示為監(jiān)聽套接字*/ int acl_is_listening_socket(ACL_SOCKET fd) {return acl_check_socket(fd) == 1; }

    SO_SNDBUF和SO_RCVBUF

    理論

    含義

    • SO_SNDBUF:TCP發(fā)送緩沖區(qū)的容量上限;
    • SO_RCVBUF:TCP接受緩沖區(qū)的容量上限;

    注意:緩沖區(qū)的上限不能無限大,如果超過內(nèi)核設(shè)置的上限值,則以內(nèi)核設(shè)置值為準(zhǔn)

    $ sysctl -a net.ipv4.tcp_rmem = 8192 87380 16777216 net.ipv4.tcp_wmem = 8192 65536 16777216 net.ipv4.tcp_mem = 8388608 12582912 16777216

    與實(shí)際使用內(nèi)存的關(guān)系?

    • SO_SNDBUF和SO_RCVBUF只是規(guī)定了讀寫緩沖區(qū)大小的上限,在實(shí)際使用未達(dá)到上限前,SO_SNDBUF和SO_RCVBUF是不起作用的。
    • 一個(gè)TCP連接占用的內(nèi)存相當(dāng)于讀寫緩沖區(qū)實(shí)際占用內(nèi)存大小之和。
    • 當(dāng)我們用setsockopt來設(shè)置TCP的接收緩沖區(qū)和發(fā)送緩沖區(qū)的大小時(shí),系統(tǒng)都會(huì)將其值加倍,并且不得小于某個(gè)值。這是為了確保一個(gè)TCP連接擁有足夠的空閑緩沖區(qū)來處理擁塞。
      • 接收緩沖區(qū)最小值一般是256
      • 發(fā)送緩沖區(qū)最小值一般是2048
    • 我們也可以強(qiáng)制修改內(nèi)存參數(shù)/proc/sys/net/ipv4/tcp_rmem和/proc/sys/net/ipv4/tcp_wmem來強(qiáng)制TCP接收緩沖區(qū)和發(fā)送緩沖區(qū)的大小沒有最小值限制

    與滑動(dòng)窗口的關(guān)系?

    接收緩存區(qū)和接收滑動(dòng)窗口關(guān)系

    接收緩存區(qū)包含了滑動(dòng)窗口,即接收緩存區(qū)大小>= 滑動(dòng)窗口大小。接受緩沖區(qū)的數(shù)據(jù)主要分為兩部分:

    • 接受滑動(dòng)窗口內(nèi)的無序的TCP報(bào)文;
    • 有序的,應(yīng)用還未讀取的數(shù)據(jù)(占用比例:1/(2^tcp_adv_win_scale),默認(rèn)tcp_adv_win_scale配置為2);

    因此,當(dāng)接受緩沖區(qū)上限固定后,如果應(yīng)用程序讀取數(shù)據(jù)的速率過慢,接收滑動(dòng)窗口會(huì)縮小,從而通知連接的對(duì)端降低發(fā)送速度,避免無謂的網(wǎng)絡(luò)傳輸。

    發(fā)送緩存區(qū)和發(fā)送滑動(dòng)窗口關(guān)系

    發(fā)送緩存區(qū)包含了發(fā)送滑動(dòng)窗口,即發(fā)送緩存區(qū)大小>= 發(fā)送滑動(dòng)窗口大小。發(fā)送緩沖區(qū)的數(shù)據(jù)主要分為兩部分:

    • 發(fā)送窗口內(nèi)的數(shù)據(jù):已發(fā)送還未確認(rèn)的數(shù)據(jù);
    • 應(yīng)用寫入的數(shù)據(jù);

    緩沖區(qū)大小預(yù)估

    一般以BDP來設(shè)置最大接收窗口,BDP叫做帶寬時(shí)延積,也就是帶寬與網(wǎng)絡(luò)時(shí)延的乘積。因?yàn)锽DP就表示了網(wǎng)絡(luò)承載能力,最大接收窗口就表示了網(wǎng)絡(luò)承載能力內(nèi)可以不經(jīng)確認(rèn)發(fā)出的報(bào)文。如下圖所示:

    根據(jù)接受窗口大小的占比1-1/(2^tcp_adv_win_scale),計(jì)算出緩沖區(qū)大小上限;

    舉例:例如若我們的帶寬為2Gbps,時(shí)延為10ms,那么帶寬時(shí)延積BDP則為2G/8 * 0.01=2.5MB,所以這樣的網(wǎng)絡(luò)中可以設(shè)最大接收窗口為2.5MB,當(dāng)tcp_adv_win_scale=2時(shí)最大讀緩存可以設(shè)為4/3*2.5MB=3.3MB。

    1. 獲取接收緩沖區(qū)的大小

    #include <stdlib.h> #include <stdio.h> #include <getopt.h> #include <zconf.h> #include <sys/socket.h>int main(int argc, char *argv[]) {int fd, val;socklen_t len;char strres[128];len = sizeof(val);fd = socket(AF_INET, SOCK_STREAM, 0);if(getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) == -1){printf("getsockopt error");exit(0);}else{if(len != sizeof(int))snprintf(strres, sizeof(strres), "sizeof (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres), "%d", val);printf("SO_RCVBUF default = %s\n", strres); // 87380}close(fd);exit(0);}

    2. 封裝

    // // Created by oceanstar on 2021/9/7. //#include <cerrno> #include <cstring> #include <msg/acl_msg.h> #include <net/acl_getsocktype.h> #include "acl_tcp_ctl.h"namespace oceanstar{/*** 設(shè)置 TCP 套接字的寫緩沖區(qū)大小* @param fd {ACL_SOCKET} 套接字* @param size {int} 緩沖區(qū)設(shè)置大小*/void acl_tcp_set_sndbuf(ACL_SOCKET fd, int size){int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return;if(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)) < 0){acl_msg_error("(%s:%d): FD %d, SIZE %d: %s\n",__LINE__, __FUNCTION__ , fd, size, strerror(errno));}}/*** 獲取 TCP 套接字的寫緩沖區(qū)大小* @param fd {ACL_SOCKET} 套接字* @return {int} 緩沖區(qū)大小*/int acl_tcp_get_sndbuf(ACL_SOCKET fd){int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return 0;int size;socklen_t len;len = (socklen_t) sizeof(size);if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, &len) < 0) {acl_msg_error("%s(%d): size(%d), getsockopt error(%s)",__LINE__, __LINE__, size, strerror(errno));return -1;}return size;}/*** 設(shè)置 TCP 套接字的讀緩沖區(qū)大小* @param fd {ACL_SOCKET} 套接字* @param size {int} 緩沖區(qū)設(shè)置大小*/void acl_tcp_set_rcvbuf(ACL_SOCKET fd, int size){int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return ;if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,(char *) &size, sizeof(size)) < 0) {acl_msg_error("%s(%d): size(%d), setsockopt error(%s)",__FILE__, __LINE__, size, strerror(errno));}}/*** 獲取 TCP 套接字的讀緩沖區(qū)大小* @param fd {ACL_SOCKET} 套接字* @return {int} 緩沖區(qū)大小*/int acl_tcp_get_rcvbuf(ACL_SOCKET fd){int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return 0;int size;socklen_t len;len = (socklen_t)sizeof(size);if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF,(char *) &size, &len) < 0){acl_msg_error("%s(%d): size(%d), getsockopt error(%s)",__FILE__, __LINE__, size, strerror(errno));return -1;}return size;} }

    2. 客戶端修改TCP發(fā)送緩沖區(qū)大小—待研究

    SO_RCVLOWAT、SO_SNDLOWAT

    SO_RCVLOWAT、SO_SNDLOWAT分別表示TCP接收緩存和發(fā)送緩沖區(qū)的低水位標(biāo)記。他們一般被IO復(fù)用系統(tǒng)調(diào)用用來判斷socket是否可讀可寫:

    • 當(dāng)TCP接收緩沖區(qū)中可讀數(shù)據(jù)的總數(shù)大于其低水位標(biāo)記時(shí),IO復(fù)用系統(tǒng)調(diào)用將通知應(yīng)用程序可以從對(duì)應(yīng)的socket上讀取數(shù)據(jù);
    • 當(dāng)TCP發(fā)送緩沖區(qū)中空閑空間的大小大于其低水位標(biāo)記時(shí),IO復(fù)用系統(tǒng)調(diào)用將通知應(yīng)用程序可以往對(duì)應(yīng)的socket上寫數(shù)據(jù)

    默認(rèn)情況下,TCP接收/發(fā)送緩沖區(qū)的低水位標(biāo)記均為1

    SO_BROADCAST套接字選項(xiàng)

    • 本選項(xiàng)開啟或禁止進(jìn)程發(fā)送廣播消息的能力。只有數(shù)據(jù)報(bào)套接字支持廣播,并且還必須是在支持廣播消息的網(wǎng)絡(luò)上(例如以太網(wǎng),令牌環(huán)網(wǎng)等)
    • 我們不可能在點(diǎn)對(duì)點(diǎn)鏈路上進(jìn)行廣播,也不可能在基于連接的傳輸協(xié)議(例如TCP和SCTP)之上進(jìn)行廣播。

    SO_DEBUG 套接字選項(xiàng)

    • 本選項(xiàng)僅由TCP支持。當(dāng)給一個(gè)TCP套接字開啟本選項(xiàng)時(shí),內(nèi)核將為TCP在該套接字發(fā)送和接受的所有分組保留詳細(xì)跟蹤信息。這些信息保存在內(nèi)核的某個(gè)環(huán)形緩沖區(qū)中,并可使用trpt程序進(jìn)行檢查。

    SO_DONTROUTE套接字選項(xiàng)

    SO_ERROR套接字選項(xiàng)

    當(dāng)一個(gè)套接字上發(fā)生錯(cuò)誤時(shí),源自Berkeley的內(nèi)核中的協(xié)議模塊將該套接字的名為so_error的變量設(shè)置為標(biāo)準(zhǔn)的Unix Exxx值中的一個(gè)。我們稱它為該套接字的待處理錯(cuò)誤。

    內(nèi)核能以下面兩種方式之一立即通知進(jìn)程這個(gè)錯(cuò)誤:

    • 如果進(jìn)程阻塞在對(duì)該套接字的select調(diào)用上,那么無論是檢查可讀條件還是可寫條件,select均返回并設(shè)置其中一個(gè)或者所有兩個(gè)條件
    • 如果進(jìn)程使用信號(hào)驅(qū)動(dòng)式IO模型,那么給進(jìn)程或者進(jìn)程組一個(gè)SIGIO信號(hào)。

    進(jìn)程然后可以通過訪問SO_ERROR套接字選項(xiàng)獲取so_error的值。由getsockopt返回的整數(shù)值就是該套接字的待處理錯(cuò)誤。so_error隨后由內(nèi)核復(fù)位為0

    • 當(dāng)進(jìn)程調(diào)用read:

      • 沒有數(shù)據(jù)返回時(shí),那么read返回-1而且errno被設(shè)置為so_error的值(非0值), so_error設(shè)復(fù)位為0
      • 如果由數(shù)據(jù)等待被讀取,那么read返回讀取到的數(shù)據(jù)。
    • 如果在進(jìn)程調(diào)用write時(shí)so_error為非0值,那么wriet返回-1而且被errno被設(shè)為so_error的值(非0值), so_error設(shè)復(fù)位為0

    SO_KEEPALIVE套接字選項(xiàng)

    SO_KEEPALIVE 保持連接檢測對(duì)方主機(jī)是否崩潰,避免(服務(wù)器)永遠(yuǎn)阻塞于TCP連接的輸入。

    設(shè)置該選項(xiàng)后,如果2小時(shí)內(nèi)在此套接口的任一方向都沒有數(shù)據(jù)交換,TCP就自動(dòng)給對(duì)方 發(fā)一個(gè)保持存活探測分節(jié)(keepalive probe)。這是一個(gè)對(duì)方必須響應(yīng)的TCP分節(jié).它會(huì)導(dǎo)致以下三種情況:

    1、對(duì)方接收一切正常:以期望的ACK響應(yīng),應(yīng)用程序無動(dòng)作(因?yàn)橐磺姓?#xff09;,又經(jīng)過沒有動(dòng)靜的2小時(shí)后,TCP將發(fā)出另一個(gè)探測分節(jié)。

    2、對(duì)方已崩潰且已重新啟動(dòng):以RST響應(yīng)。套接口的待處理錯(cuò)誤被置為ECONNRESET,套接 口本身則被關(guān)閉。

    3、對(duì)方無任何響應(yīng):源自berkeley的TCP發(fā)送另外8個(gè)探測分節(jié),相隔75秒一個(gè),試圖得到一個(gè)響應(yīng)。在發(fā)出第一個(gè)探測分節(jié)11分鐘15秒后若仍無響應(yīng)就放棄。

    • 如果該套接字沒有任何響應(yīng),套接口的待處理錯(cuò)誤被置為ETIMEOUT,套接口本身則被關(guān)閉。
    • 如果該套接字收到ICMP響應(yīng),ICMP錯(cuò)誤是“host unreachable(主機(jī)不可達(dá))”,這種情況下待處理錯(cuò)誤被置為 EHOSTUNREACH。

    SO_LINGER

    • 作用: 指定close函數(shù)對(duì) 面對(duì)連接的協(xié)議(TCP、SCTP,但不是UDP)如何操作
    • 說明:在默認(rèn)情況下,當(dāng)調(diào)用close關(guān)閉socket的使用,close會(huì)立即返回,但是,如果send buffer中還有數(shù)據(jù),系統(tǒng)會(huì)試著先把send buffer中的數(shù)據(jù)發(fā)送出去,然后close才返回。SO_LINGER選項(xiàng)則是用來修改這種默認(rèn)操作的

    SO_LINGER要求在用戶進(jìn)程和內(nèi)核間傳遞如下結(jié)構(gòu):

    #include <sys/socket.h> struct linger { int l_onoff //0=off, nonzero=on(開關(guān)) int l_linger //linger time(延遲時(shí)間) }

    (1)如果l_onoff=0,則關(guān)閉這個(gè)選項(xiàng)。采用默認(rèn)操作
    (2)如果l_onoff!=0 l_linger =0:

    • close調(diào)用立即返回
    • TCP模塊將通過發(fā)送RST(復(fù)位)分組而不是用正常的FIN|ACK|FIN|ACK四個(gè)分組來關(guān)閉該連接。
    • 至于發(fā)送緩沖區(qū)中如果有未發(fā)送完的數(shù)據(jù),則丟棄。
    • 主動(dòng)關(guān)閉一方的TCP狀態(tài)則跳過TIMEWAIT,直接進(jìn)入CLOSED。

    網(wǎng)上很多人想利用這一點(diǎn)來解決服務(wù)器上出現(xiàn)大量的TIMEWAIT狀態(tài)的socket的問題,但是,這并不是一個(gè)好主意,這種關(guān)閉方式的用途并不在這兒,實(shí)際用途在于服務(wù)器在應(yīng)用層的需求。
    (3)如果l_onoff!=0 l_linger >0:
    此時(shí)close的行為取決于兩個(gè)條件:

    • 被關(guān)閉的socket對(duì)應(yīng)的TCP發(fā)送緩沖區(qū)中是否還有殘留的數(shù)據(jù)
    • 被關(guān)閉的socket是阻塞的還是非阻塞的。
      • 如果是阻塞的,close將等待l_linger時(shí)間,直到TCP模塊發(fā)送完殘留數(shù)據(jù)并得到對(duì)方的確認(rèn)。如果這段時(shí)間內(nèi)TCP模塊沒有確認(rèn),那么close返回將返回-1并設(shè)置errno為EWOULDBLOCK
      • 如果是非阻塞的,close立即返回,我們通過返回值和error來判斷殘留數(shù)據(jù)是否已經(jīng)發(fā)送完畢
    /*** 設(shè)置 TCP 套接字的 SO_LINGER 選項(xiàng)* @param fd {ACL_SOCKET} 套接字* @param onoff {int} 是否啟用 SO_LINGER 選項(xiàng)* @param timeout {int} 當(dāng)SO_LINGER打開時(shí),取消 timed_wait 的時(shí)間,單位為秒*/void acl_tcp_so_linger(ACL_SOCKET fd, int onoff, int timeout){struct linger l;int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return;l.l_onoff = onoff ? 1 : 0;l.l_linger = timeout >= 0 ? timeout : 0;if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)) < 0) {acl_msg_error("%s(%d): setsockopt(SO_LINGER) error(%s),"" onoff(%d), timeout(%d)", __FUNCTION__ , __LINE__,strerror(errno), onoff, timeout);}}/*** 獲得 TCP 套接字的 linger 值* @param fd {ACL_SOCKET} 套接字* @return {int} 返回 -1 表示未設(shè)置 linger 選項(xiàng)或內(nèi)部出錯(cuò),>= 0 表示設(shè)置了* linger 選項(xiàng)且該值表示套接字關(guān)閉后該 TCP 連接在內(nèi)核中維持 TIME_WAIT 狀態(tài)* 的逗留時(shí)間(秒)*/int acl_get_tcp_solinger(ACL_SOCKET fd){int n = acl_getsocktype(fd);if (n != AF_INET && n != AF_INET6)return -1;struct linger l;socklen_t len = (socklen_t) sizeof(l);memset(&l, 0, sizeof(l));if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char*) &l, &len) < 0) {acl_msg_error("%s(%d): getsockopt error: %s, fd: %d",__FILE__, __LINE__, strerror(errno), fd);return -1;}return l.l_linger == 0 ? -1 : l.l_linger;}

    SO_ERROR

    當(dāng)一個(gè)套接字上發(fā)生錯(cuò)誤時(shí),內(nèi)核協(xié)議中的協(xié)議模塊將此套接字的名為so_error的變量設(shè)為標(biāo)準(zhǔn)的Unix Exxx值中的一個(gè),我們稱它為該套接字上的待處理錯(cuò)誤(pending error)

    內(nèi)核能夠以下面兩種方式之一立即通知進(jìn)程這個(gè)錯(cuò)誤:

    • 如果進(jìn)程阻塞在對(duì)該套接字的select調(diào)用上,那么無論是檢查可讀還是可寫條件,select均返回并設(shè)置其中一個(gè)或者所有兩個(gè)條件

    • 如果進(jìn)程使用信號(hào)驅(qū)動(dòng)式IO模型,那就給進(jìn)程或者進(jìn)程組產(chǎn)生一個(gè)SIGIO信號(hào)

      進(jìn)程然后可以通過訪問SO_ERROR套接字選項(xiàng)獲取so_error的值。由getsockopt返回的整數(shù)值就是該套接字的待處理錯(cuò)誤。so_error隨后由內(nèi)核復(fù)位為0.

    • 當(dāng)進(jìn)程調(diào)用read且沒有數(shù)據(jù)返回時(shí),如果so_error為非0值,那么read返回-1且errno被置為so_error的值。so_error隨后被復(fù)位為0。如果該套接字上有數(shù)據(jù)在排隊(duì)等待讀取,那么read返回那些數(shù)據(jù)而不是返回錯(cuò)誤條件。

    • 如果在進(jìn)程調(diào)用write時(shí)so_error為非0值,那么write返回-1且errno被設(shè)為so_error的值。so_error隨后被復(fù)位為0。

    這是一個(gè)可以獲取但不能設(shè)置的套接字選項(xiàng)。

    xxxxxwait_write(fe);len = sizeof(err);ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len);if (ret == 0 && err == 0) {SOCK_ADDR saddr;struct sockaddr *sa = (struct sockaddr*) &saddr;socklen_t n = sizeof(saddr);if (getpeername(sockfd, sa, &n) == 0) {return 0;}return -1;}return -1;

    SO_RCVTIMEO, SO_SNDTIMEO

    • 套接字選項(xiàng)SO_RCVTIMEO: 用來設(shè)置socket接收數(shù)據(jù)的超時(shí)時(shí)間;
    • 套接字選項(xiàng)SO_SNDTIMEO: 用來設(shè)置socket發(fā)送數(shù)據(jù)的超時(shí)時(shí)間;

    問:一般情況下,調(diào)用accept/connect/send/secv,進(jìn)程會(huì)阻塞,但是如果對(duì)端異常,進(jìn)程可能無法正常退出等待。如何讓這些調(diào)用自動(dòng)定時(shí)退出
    答:可以使用比如alarm定時(shí)器、IO復(fù)用設(shè)置定時(shí)器,還可以使用socket編程里函數(shù)級(jí)別的socket套接字選項(xiàng)SO_RCVTIMEO和SO_SNDTIMEO,僅針對(duì)于數(shù)據(jù)接收和發(fā)送相關(guān),而無需設(shè)置專門的信號(hào)捕獲函數(shù)。

    能夠作用的系統(tǒng)調(diào)用包括:send、sendmsg、recv、recvmsg、accept、connect。

    系統(tǒng)調(diào)用有效選項(xiàng)系統(tǒng)調(diào)用超時(shí)后的行為
    sendSO_SNDTIMEO返回-1,設(shè)置errno為EAGAIN或EWOULDBLOCK
    sendmsgSO_SNDTIMEO返回-1,設(shè)置errno為EAGAIN或EWOULDBLOCK
    recvSO_RCVTIMEO返回-1,設(shè)置errno為EAGAIN或EWOULDBLOCK
    recvmsgSO_RCVTIMEO返回-1,設(shè)置errno為EAGAIN或EWOULDBLOCK
    acceptSO_RCVTIMEO返回-1,設(shè)置errno為EAGAIN或EWOULDBLOCK
    connectSO_SNDTIMEO返回-1,設(shè)置errno為EINPROGRESS

    注意:

    • EAGAIN通常和EWOULDBLOCK是同一個(gè)值;
    • SO_RCVTIMEO, SO_SNDTIMEO不要求系統(tǒng)調(diào)用對(duì)應(yīng)fd是非阻塞(nonblocking)的,但是使用了該套接字選項(xiàng)的sock fd,會(huì)成為nonblocking(即使之前是blocking)的

    示例1:設(shè)置connect超時(shí)時(shí)間

    根據(jù)系統(tǒng)調(diào)用accept的返回值,以及errno判斷超時(shí)時(shí)間是否已到,從而決定是否開始處理超時(shí)定時(shí)任務(wù)。

    客戶端程序:超時(shí)連接服務(wù)器

    /*** 客戶端程序* 連接服務(wù)器,超時(shí)報(bào)錯(cuò)、返回* build:* $ gcc timeout_connect.c*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <assert.h>/* 超時(shí)連接 */ int timeout_connect (const char *ip, int port, int time) {int ret = 0;struct sockaddr_in servaddr;printf("client start...\n");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;inet_pton(AF_INET, ip, &servaddr.sin_addr);servaddr.sin_port = htons(port);int sockfd = socket(AF_INET, SOCK_STREAM, 0);assert(sockfd >= 0);/* 通過選項(xiàng)SO_RCVTIMEO和SO_SNDTIMEO設(shè)置的超時(shí)時(shí)間的類型時(shí)timeval, 和select系統(tǒng)調(diào)用的超時(shí)參數(shù)類型相同 */struct timeval timeout;timeout.tv_sec = time;timeout.tv_usec = 0;socklen_t len = sizeof(timeout);ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, len);if (ret == -1) {perror("setsockopt error");return -1;}if ((ret = connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) {/* 超時(shí)對(duì)于errno 為EINPROGRESS. 下面條件如果成立,就可以處理定時(shí)任務(wù)了 */if (errno == EINPROGRESS) {perror("connecting timeout, process timeout logic");return -1;}perror("error occur when connecting to server\n");}return sockfd; }int main(int argc, char *argv[]) {if (argc <= 2) {printf("usage: %s ip_address port_number\n", argv[0]);return 1;}const char *ip = argv[1];int port = atoi(argv[2]);printf("connect %s:%d...\n", ip, port);int sockfd = timeout_connect(ip, port, 10);if (sockfd < 0) {perror("timeout_connect error");return 1;}return 0; }

    運(yùn)行結(jié)果(隨意輸入一個(gè)服務(wù)器IP、端口):

    $ ./timeout_connect 192.168.0.105 8000 connect 192.168.0.105:8000... client start... connecting timeout, process timeout logic: Operation now in progress timeout_connect error: Operation now in progress

    可以看到,本來阻塞的connect調(diào)用,10秒后返回-1,并且errno設(shè)置為EINPROGRESS。

    示例2:超時(shí)接收(服務(wù)器數(shù)據(jù))

    服務(wù)端

    監(jiān)聽本地任意IP地址,端口8001
    從鍵盤輸入一行數(shù)據(jù),就發(fā)送給用戶;如果沒有數(shù)據(jù),就阻塞。

    /*** 服務(wù)器程序* 示例:超時(shí)接收服務(wù)器數(shù)據(jù),超時(shí)時(shí)間例程中設(shè)置為10秒* 編譯: $ gcc timeout_recv_server.c -o server* 運(yùn)行方式:* $ ./server* 默認(rèn)監(jiān)聽端口8001(根據(jù)實(shí)際情況修改)* 服務(wù)器功能:從鍵盤接收用戶輸入,每接收一行就向客戶輸出一行。如果沒有用戶輸入,* 則阻塞。* 客戶端需要跟服務(wù)器安裝在同一網(wǎng)段上,為了測試方便,就直接都安裝到同一機(jī)器上*/ #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <arpa/inet.h> #include <signal.h>int sockfd = -1;void sig_func(int sig_no) {if (sig_no == SIGINT || sig_no == SIGTERM) {if (sockfd >= 0) {close(sockfd);}exit(1);} }int main() {struct sockaddr_in servaddr, cliaddr;int listenfd;signal(SIGINT, sig_func);printf("server start...\n");if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("socket error");exit(1);}sockfd = listenfd;int on = 1;if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {perror("setsocketopt error");exit(1);}bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;// servaddr.sin_addr.s_addr = INADDR_ANY;inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);servaddr.sin_port = htons(8001);if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind error");exit(1);}if (listen(listenfd, 5) < 0) {perror("listen error");exit(1);}char buf[1024];socklen_t clilen = sizeof(cliaddr);int connfd;if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen)) < 0) {perror("accept error");exit(1);}printf("input a line string: \n");int nbytes;while (fgets(buf, sizeof(buf), stdin)) {nbytes = send(connfd, buf, strlen(buf), 0);if (nbytes < 0) {perror("send error");break;}else if (nbytes == 0) {}printf("send: %s\n", buf);}close(connfd);close(listenfd);return 0; }

    客戶端

    設(shè)置10秒超時(shí),接收服務(wù)器數(shù)據(jù)。

    客戶端10秒以內(nèi),接收到服務(wù)器數(shù)據(jù),則直接打印;超過10秒,就報(bào)錯(cuò)退出。

    /*** 客戶端程序* 示例:超時(shí)接收服務(wù)器數(shù)據(jù),超時(shí)時(shí)間例程中設(shè)置為10秒* 編譯: $ gcc timeout_recv_client.c -o client* 運(yùn)行方式:* 如本地運(yùn)行(對(duì)應(yīng)服務(wù)器實(shí)際監(jiān)聽的IP地址和端口號(hào)) $ ./client 127.0.0.1 8001*/ #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <arpa/inet.h>int timeout_recv(int fd, char *buf, int len, int nsec) {struct timeval timeout;timeout.tv_sec = nsec;timeout.tv_usec = 0;printf("timeout_recv called, timeout %d seconds\n", nsec);if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {perror("setsockopt error");exit(1);}int n = recv(fd, buf, len, 0);return n; }int main(int argc, char *argv[]) {if (argc != 3) {printf("usage: %s <ip address> <port>\n", argv[0]);}char *ip = argv[1];uint16_t port = atoi(argv[2]);printf("client start..\n");printf("connect to %s:%d\n", ip, port);int sockfd;if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("socket error");exit(1);}struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;inet_pton(AF_INET, ip, &servaddr.sin_addr);servaddr.sin_port = htons(port);int connfd;if ((connfd = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0) {perror("connect error");exit(1);}printf("success to connect server %s:%d\n", ip, port);printf("wait for server's response\n");char buf[100];while (1) {int nread;nread = timeout_recv(sockfd, buf, sizeof(buf), 10);if (nread < 0) {perror("timeout_recv error");exit(1);}else if (nread == 0) {shutdown(sockfd, SHUT_RDWR);break;}write(STDOUT_FILENO, buf, nread);}return 0; }

    客戶端運(yùn)行結(jié)果:
    可以看到,超過10秒后,客戶端自動(dòng)退出程序,而不再阻塞在recv。

    $ ./client 127.0.0.1 8001 client start.. connect to 127.0.0.1:8001 success to connect server 127.0.0.1:8001 wait for server's response timeout_recv called, timeout 10 seconds hello # 服務(wù)器端用戶輸入數(shù)據(jù) timeout_recv called, timeout 10 seconds nihao # 服務(wù)器端用戶輸入數(shù)據(jù) timeout_recv called, timeout 10 seconds timeout_recv error: Resource temporarily unavailable # 服務(wù)器端超時(shí)未輸入數(shù)據(jù),客戶端程序運(yùn)行結(jié)束

    總結(jié)

    以上是生活随笔為你收集整理的Linux C/C++编程:setsockopt、getsockopt的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产精品无码一区二区三区不卡 | 国产无av码在线观看 | 好男人社区资源 | 天堂在线观看www | 亚洲综合在线一区二区三区 | 国产精品久久久久影院嫩草 | 亚洲精品一区二区三区在线 | 欧美性色19p | 国产精品久久国产精品99 | 国产精品第一区揄拍无码 | 国产av无码专区亚洲a∨毛片 | 国产成人无码午夜视频在线观看 | 色狠狠av一区二区三区 | 亚洲人成无码网www | 一本无码人妻在中文字幕免费 | 国产精品第一国产精品 | 牲欲强的熟妇农村老妇女 | 国产明星裸体无码xxxx视频 | 久久国产36精品色熟妇 | 男女下面进入的视频免费午夜 | 国产免费久久久久久无码 | 亚洲人成网站色7799 | 国产精品久久福利网站 | 成人性做爰aaa片免费看不忠 | 成年美女黄网站色大免费全看 | 亚洲日韩乱码中文无码蜜桃臀网站 | 人妻无码久久精品人妻 | 欧美人妻一区二区三区 | 麻豆国产人妻欲求不满谁演的 | 欧美激情一区二区三区成人 | 少妇无套内谢久久久久 | 婷婷丁香五月天综合东京热 | 国产又爽又黄又刺激的视频 | 成年女人永久免费看片 | 亚洲精品久久久久中文第一幕 | 色一情一乱一伦一区二区三欧美 | 亚洲乱码国产乱码精品精 | 久久精品国产亚洲精品 | 久久久久久九九精品久 | 性色av无码免费一区二区三区 | 久久久久久久久888 | 亚洲中文字幕无码中文字在线 | 亚洲欧洲中文日韩av乱码 | 日本精品久久久久中文字幕 | 国产av人人夜夜澡人人爽麻豆 | 国产va免费精品观看 | 亚洲中文字幕成人无码 | 成人精品天堂一区二区三区 | 成人无码视频免费播放 | 亚洲 a v无 码免 费 成 人 a v | 扒开双腿吃奶呻吟做受视频 | 国产精品久久久av久久久 | 国产成人无码一二三区视频 | 女人被男人躁得好爽免费视频 | 麻豆成人精品国产免费 | 亚洲色大成网站www国产 | 亚洲欧洲无卡二区视頻 | 国产亚洲精品久久久闺蜜 | 国产精品久久久久7777 | 欧美xxxxx精品 | 精品国产精品久久一区免费式 | 99久久婷婷国产综合精品青草免费 | 自拍偷自拍亚洲精品被多人伦好爽 | 成 人 网 站国产免费观看 | 色综合天天综合狠狠爱 | 人人澡人人透人人爽 | 熟女少妇人妻中文字幕 | 日本饥渴人妻欲求不满 | 2020久久香蕉国产线看观看 | 国产一区二区不卡老阿姨 | 成人亚洲精品久久久久 | 男女性色大片免费网站 | 国产精品igao视频网 | av无码久久久久不卡免费网站 | 精品国产一区二区三区av 性色 | 国产成人无码午夜视频在线观看 | 欧美真人作爱免费视频 | 欧美人妻一区二区三区 | 国产亚洲精品久久久久久久 | 99er热精品视频 | 亚洲精品一区国产 | 国产激情无码一区二区app | 婷婷综合久久中文字幕蜜桃三电影 | 色诱久久久久综合网ywww | 国精品人妻无码一区二区三区蜜柚 | 中文字幕无码乱人伦 | 综合人妻久久一区二区精品 | 久久亚洲精品中文字幕无男同 | 人妻少妇精品无码专区二区 | 日韩人妻无码中文字幕视频 | 亚洲色欲色欲天天天www | 亚洲精品欧美二区三区中文字幕 | 成熟女人特级毛片www免费 | 最近中文2019字幕第二页 | 天天av天天av天天透 | 日韩欧美成人免费观看 | 色诱久久久久综合网ywww | av在线亚洲欧洲日产一区二区 | 国内精品人妻无码久久久影院 | 一个人免费观看的www视频 | 人妻体内射精一区二区三四 | 国产麻豆精品一区二区三区v视界 | 精品久久久久久人妻无码中文字幕 | 亚洲色大成网站www | 日本一区二区三区免费播放 | 亚洲精品国产第一综合99久久 | 欧美 日韩 亚洲 在线 | www国产精品内射老师 | 99久久99久久免费精品蜜桃 | 国产精品久久久久无码av色戒 | 俄罗斯老熟妇色xxxx | 无码一区二区三区在线 | 日韩av无码一区二区三区 | 亚洲日韩av片在线观看 | 午夜成人1000部免费视频 | 欧美三级a做爰在线观看 | 日本一卡2卡3卡四卡精品网站 | 亚洲天堂2017无码中文 | 日本一区二区更新不卡 | 精品国产乱码久久久久乱码 | 欧美日本精品一区二区三区 | 成熟妇人a片免费看网站 | 日本爽爽爽爽爽爽在线观看免 | 两性色午夜视频免费播放 | 亚洲精品成a人在线观看 | 狠狠综合久久久久综合网 | 5858s亚洲色大成网站www | 国产亚洲欧美日韩亚洲中文色 | 国产精品a成v人在线播放 | 日韩人妻无码一区二区三区久久99 | 99久久久无码国产精品免费 | 国产av一区二区三区最新精品 | 国产午夜福利100集发布 | 国产欧美熟妇另类久久久 | 88国产精品欧美一区二区三区 | 台湾无码一区二区 | 亚洲欧美综合区丁香五月小说 | 少妇人妻av毛片在线看 | 人妻互换免费中文字幕 | 免费乱码人妻系列无码专区 | 搡女人真爽免费视频大全 | 18无码粉嫩小泬无套在线观看 | 亚洲成a人一区二区三区 | 波多野结衣乳巨码无在线观看 | 亚洲中文字幕在线观看 | 国精产品一区二区三区 | 国产97人人超碰caoprom | 久久久中文久久久无码 | 粉嫩少妇内射浓精videos | 亚洲自偷自偷在线制服 | 久久亚洲a片com人成 | 国产激情一区二区三区 | 丰满人妻一区二区三区免费视频 | 久久久久久久人妻无码中文字幕爆 | 久久亚洲精品中文字幕无男同 | 丰满岳乱妇在线观看中字无码 | 久久亚洲中文字幕精品一区 | 国产精品久久久久久久9999 | 欧美野外疯狂做受xxxx高潮 | 日韩精品无码一区二区中文字幕 | 窝窝午夜理论片影院 | 国内精品久久久久久中文字幕 | 国产特级毛片aaaaaa高潮流水 | 狠狠cao日日穞夜夜穞av | 任你躁在线精品免费 | 久久亚洲中文字幕精品一区 | 狠狠色丁香久久婷婷综合五月 | 亚洲第一网站男人都懂 | 国产精品久久久久影院嫩草 | 99re在线播放 | 国产成人人人97超碰超爽8 | 波多野结衣 黑人 | 国内精品人妻无码久久久影院 | 免费无码av一区二区 | 任你躁在线精品免费 | 欧洲美熟女乱又伦 | 国产美女极度色诱视频www | 国产精品二区一区二区aⅴ污介绍 | 狠狠色噜噜狠狠狠7777奇米 | 中文字幕无码av激情不卡 | 国产又爽又猛又粗的视频a片 | www国产亚洲精品久久网站 | 最新国产乱人伦偷精品免费网站 | 久久精品99久久香蕉国产色戒 | 男女超爽视频免费播放 | 国产亚洲精品久久久久久 | a国产一区二区免费入口 | 国产电影无码午夜在线播放 | a片免费视频在线观看 | 亚洲а∨天堂久久精品2021 | 内射老妇bbwx0c0ck | 人人爽人人澡人人人妻 | 亚洲成av人片天堂网无码】 | 国产精品丝袜黑色高跟鞋 | 午夜无码人妻av大片色欲 | 中文字幕人妻无码一夲道 | 中文字幕乱码亚洲无线三区 | 久久久久久久女国产乱让韩 | 美女扒开屁股让男人桶 | 99麻豆久久久国产精品免费 | 日韩欧美成人免费观看 | 最近免费中文字幕中文高清百度 | 亚洲精品一区二区三区四区五区 | а天堂中文在线官网 | 青青草原综合久久大伊人精品 | 兔费看少妇性l交大片免费 | 激情综合激情五月俺也去 | ass日本丰满熟妇pics | 日本丰满护士爆乳xxxx | 亚洲成a人片在线观看无码 | 久久综合香蕉国产蜜臀av | 熟妇人妻无码xxx视频 | 国产成人无码区免费内射一片色欲 | 男女作爱免费网站 | 日日碰狠狠丁香久燥 | 久久国产精品精品国产色婷婷 | 国精品人妻无码一区二区三区蜜柚 | 国内精品久久久久久中文字幕 | 97无码免费人妻超级碰碰夜夜 | 成人av无码一区二区三区 | 久久99精品久久久久婷婷 | 久久久久se色偷偷亚洲精品av | 久久国产精品萌白酱免费 | 日本在线高清不卡免费播放 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产精品久久国产三级国 | 波多野结衣一区二区三区av免费 | 中文字幕人妻丝袜二区 | 无码国产激情在线观看 | 亚洲中文字幕在线无码一区二区 | 午夜成人1000部免费视频 | 在线欧美精品一区二区三区 | 少妇久久久久久人妻无码 | 国产无遮挡又黄又爽免费视频 | av在线亚洲欧洲日产一区二区 | 香蕉久久久久久av成人 | 午夜福利试看120秒体验区 | 国产精品资源一区二区 | 无遮挡啪啪摇乳动态图 | 无遮挡国产高潮视频免费观看 | 日本在线高清不卡免费播放 | 亚洲日韩av一区二区三区四区 | 久久久久av无码免费网 | 日日摸天天摸爽爽狠狠97 | 日本护士xxxxhd少妇 | 国产xxx69麻豆国语对白 | 国产成人av免费观看 | 国产 精品 自在自线 | 精品人人妻人人澡人人爽人人 | 中文字幕无码av激情不卡 | 亚洲国产精华液网站w | 成熟女人特级毛片www免费 | 精品欧洲av无码一区二区三区 | 荫蒂被男人添的好舒服爽免费视频 | 男人扒开女人内裤强吻桶进去 | 欧美亚洲日韩国产人成在线播放 | 成年女人永久免费看片 | 国产精品久久久 | 亚洲成a人一区二区三区 | 国产亚洲精品久久久ai换 | 日本熟妇乱子伦xxxx | 人人妻人人澡人人爽欧美一区 | 欧美日本免费一区二区三区 | 丁香花在线影院观看在线播放 | 人人爽人人爽人人片av亚洲 | 一本加勒比波多野结衣 | 日韩视频 中文字幕 视频一区 | 波多野结衣高清一区二区三区 | 午夜肉伦伦影院 | 日韩成人一区二区三区在线观看 | 亚洲欧洲无卡二区视頻 | 天堂久久天堂av色综合 | 99久久久无码国产精品免费 | aⅴ亚洲 日韩 色 图网站 播放 | 无遮无挡爽爽免费视频 | 男人的天堂av网站 | 一本久道高清无码视频 | 美女毛片一区二区三区四区 | 婷婷六月久久综合丁香 | 人人妻人人澡人人爽欧美精品 | 久久综合色之久久综合 | 天天摸天天透天天添 | 日本va欧美va欧美va精品 | 一个人免费观看的www视频 | 国产精品毛多多水多 | 国产亚洲日韩欧美另类第八页 | 狂野欧美性猛交免费视频 | 久久zyz资源站无码中文动漫 | 亚洲成av人片在线观看无码不卡 | 久久午夜无码鲁丝片午夜精品 | 领导边摸边吃奶边做爽在线观看 | 欧美一区二区三区视频在线观看 | 国产日产欧产精品精品app | 蜜桃视频韩日免费播放 | 人妻插b视频一区二区三区 | 欧美人与善在线com | 国产成人精品一区二区在线小狼 | 欧美性生交xxxxx久久久 | 国产suv精品一区二区五 | 久久久久久a亚洲欧洲av冫 | 97精品人妻一区二区三区香蕉 | 亚洲欧洲日本综合aⅴ在线 | 天天做天天爱天天爽综合网 | 国产女主播喷水视频在线观看 | 一本加勒比波多野结衣 | 最近免费中文字幕中文高清百度 | 人妻无码αv中文字幕久久琪琪布 | 午夜精品一区二区三区的区别 | 九九久久精品国产免费看小说 | 黑人玩弄人妻中文在线 | 55夜色66夜色国产精品视频 | 曰本女人与公拘交酡免费视频 | 日日夜夜撸啊撸 | 97精品国产97久久久久久免费 | 欧美丰满老熟妇xxxxx性 | 亚洲天堂2017无码中文 | 丰满肥臀大屁股熟妇激情视频 | 久久久久免费看成人影片 | 国产亚洲精品久久久久久久 | 51国偷自产一区二区三区 | 鲁大师影院在线观看 | 色诱久久久久综合网ywww | 成人亚洲精品久久久久软件 | 国产内射爽爽大片视频社区在线 | 国产特级毛片aaaaaa高潮流水 | 国产亚洲精品久久久久久 | 久久综合九色综合97网 | 亚洲 a v无 码免 费 成 人 a v | 装睡被陌生人摸出水好爽 | 55夜色66夜色国产精品视频 | 日韩人妻系列无码专区 | 日产精品高潮呻吟av久久 | 国产一区二区三区精品视频 | 亚洲成av人片在线观看无码不卡 | 欧美三级不卡在线观看 | 狠狠噜狠狠狠狠丁香五月 | 国产成人无码专区 | 无码任你躁久久久久久久 | 中文无码成人免费视频在线观看 | 国内丰满熟女出轨videos | 日韩在线不卡免费视频一区 | 午夜无码人妻av大片色欲 | 东京一本一道一二三区 | 少妇人妻av毛片在线看 | 精品夜夜澡人妻无码av蜜桃 | 娇妻被黑人粗大高潮白浆 | 国产网红无码精品视频 | 真人与拘做受免费视频一 | 狠狠亚洲超碰狼人久久 | 动漫av网站免费观看 | 国产成人久久精品流白浆 | 毛片内射-百度 | 国产精品无码一区二区桃花视频 | 国产偷自视频区视频 | 亚洲毛片av日韩av无码 | 帮老师解开蕾丝奶罩吸乳网站 | 国精品人妻无码一区二区三区蜜柚 | 波多野结衣一区二区三区av免费 | 乱码av麻豆丝袜熟女系列 | 欧美熟妇另类久久久久久不卡 | 精品国精品国产自在久国产87 | 无码人妻丰满熟妇区五十路百度 | 十八禁视频网站在线观看 | 色一情一乱一伦一区二区三欧美 | 亚洲日韩乱码中文无码蜜桃臀网站 | 国产精品久久久久影院嫩草 | 亚洲毛片av日韩av无码 | 中文字幕乱码人妻二区三区 | 国产午夜无码视频在线观看 | 奇米影视888欧美在线观看 | 久久99精品久久久久婷婷 | 欧洲精品码一区二区三区免费看 | 国产av一区二区三区最新精品 | 国产69精品久久久久app下载 | 国内揄拍国内精品少妇国语 | 久久精品一区二区三区四区 | a在线亚洲男人的天堂 | 久久午夜无码鲁丝片午夜精品 | 67194成是人免费无码 | 亚洲va欧美va天堂v国产综合 | 67194成是人免费无码 | 一本色道婷婷久久欧美 | 亚洲成在人网站无码天堂 | 国产精品视频免费播放 | 久久久精品欧美一区二区免费 | 亚洲啪av永久无码精品放毛片 | 亚洲aⅴ无码成人网站国产app | 粗大的内捧猛烈进出视频 | 国产人妻精品午夜福利免费 | av无码不卡在线观看免费 | 熟妇人妻无乱码中文字幕 | 亚洲人成影院在线无码按摩店 | 波多野结衣 黑人 | 精品久久综合1区2区3区激情 | 日日鲁鲁鲁夜夜爽爽狠狠 | 蜜桃视频插满18在线观看 | 少女韩国电视剧在线观看完整 | www成人国产高清内射 | 日日碰狠狠丁香久燥 | 美女扒开屁股让男人桶 | 久久久久成人精品免费播放动漫 | 丰满诱人的人妻3 | 日本丰满护士爆乳xxxx | 乱人伦中文视频在线观看 | 少妇性俱乐部纵欲狂欢电影 | 精品人妻人人做人人爽夜夜爽 | 无码一区二区三区在线观看 | 欧美亚洲日韩国产人成在线播放 | 亚洲男人av天堂午夜在 | 亚洲一区二区三区偷拍女厕 | 欧洲极品少妇 | 国内少妇偷人精品视频免费 | 国产成人无码a区在线观看视频app | 99视频精品全部免费免费观看 | 俺去俺来也在线www色官网 | 好爽又高潮了毛片免费下载 | 乱人伦中文视频在线观看 | 亚洲天堂2017无码中文 | 国产小呦泬泬99精品 | 久久精品无码一区二区三区 | 麻豆av传媒蜜桃天美传媒 | av无码电影一区二区三区 | 国产精品.xx视频.xxtv | 久久精品国产亚洲精品 | 国产欧美亚洲精品a | 亚洲国产一区二区三区在线观看 | 人妻少妇被猛烈进入中文字幕 | 国产成人无码区免费内射一片色欲 | 中文字幕无码热在线视频 | 无遮无挡爽爽免费视频 | 人妻天天爽夜夜爽一区二区 | 内射巨臀欧美在线视频 | 亚洲人亚洲人成电影网站色 | 久久99精品久久久久久 | 欧美三级a做爰在线观看 | 女人高潮内射99精品 | 色窝窝无码一区二区三区色欲 | 午夜精品一区二区三区的区别 | 亚洲aⅴ无码成人网站国产app | 亚欧洲精品在线视频免费观看 | 狠狠综合久久久久综合网 | 极品尤物被啪到呻吟喷水 | 性欧美熟妇videofreesex | 色五月丁香五月综合五月 | 蜜桃臀无码内射一区二区三区 | 国产成人无码午夜视频在线观看 | 内射巨臀欧美在线视频 | 狂野欧美激情性xxxx | 99精品无人区乱码1区2区3区 | 理论片87福利理论电影 | 精品国产麻豆免费人成网站 | 又大又黄又粗又爽的免费视频 | 精品人妻人人做人人爽夜夜爽 | 99在线 | 亚洲 | 国产97色在线 | 免 | 又大又紧又粉嫩18p少妇 | 中文字幕 亚洲精品 第1页 | 亚洲乱码日产精品bd | 日韩精品无码一区二区中文字幕 | 美女毛片一区二区三区四区 | 7777奇米四色成人眼影 | 无码人妻av免费一区二区三区 | 18禁止看的免费污网站 | 1000部啪啪未满十八勿入下载 | 小泽玛莉亚一区二区视频在线 | 亚洲熟妇色xxxxx欧美老妇 | 天干天干啦夜天干天2017 | 日本www一道久久久免费榴莲 | 无遮挡啪啪摇乳动态图 | 性欧美videos高清精品 | 中文字幕人妻丝袜二区 | 久久久精品成人免费观看 | 无码成人精品区在线观看 | 精品偷拍一区二区三区在线看 | 亚洲の无码国产の无码影院 | 精品无码成人片一区二区98 | 亚洲精品无码国产 | 少妇久久久久久人妻无码 | 亚洲中文字幕无码一久久区 | 18禁止看的免费污网站 | 黄网在线观看免费网站 | 欧美老熟妇乱xxxxx | 又粗又大又硬毛片免费看 | 人妻插b视频一区二区三区 | 欧美性生交xxxxx久久久 | 97无码免费人妻超级碰碰夜夜 | 亚洲中文字幕av在天堂 | 狠狠噜狠狠狠狠丁香五月 | 亚洲国产欧美日韩精品一区二区三区 | 中文无码成人免费视频在线观看 | 嫩b人妻精品一区二区三区 | 精品无人区无码乱码毛片国产 | 东京无码熟妇人妻av在线网址 | 中国大陆精品视频xxxx | 国产三级久久久精品麻豆三级 | 精品国产国产综合精品 | 久久国产自偷自偷免费一区调 | 色一情一乱一伦一视频免费看 | 欧美亚洲日韩国产人成在线播放 | 成人免费视频一区二区 | 乌克兰少妇xxxx做受 | 亚洲最大成人网站 | 国产精品高潮呻吟av久久4虎 | 日本大香伊一区二区三区 | 午夜熟女插插xx免费视频 | 丰满妇女强制高潮18xxxx | 精品久久8x国产免费观看 | 黑人玩弄人妻中文在线 | 国产av一区二区精品久久凹凸 | 国产午夜手机精彩视频 | 国产精品丝袜黑色高跟鞋 | 亚洲中文字幕无码一久久区 | 国内精品九九久久久精品 | 无码国产乱人伦偷精品视频 | 无码国内精品人妻少妇 | 中国大陆精品视频xxxx | 久久精品国产精品国产精品污 | 国产肉丝袜在线观看 | 欧美真人作爱免费视频 | 午夜无码区在线观看 | 天天摸天天透天天添 | 日本乱人伦片中文三区 | 人人爽人人爽人人片av亚洲 | 色一情一乱一伦一区二区三欧美 | 福利一区二区三区视频在线观看 | 国产无套粉嫩白浆在线 | 亚洲人成无码网www | 精品熟女少妇av免费观看 | 亚洲国产精品久久人人爱 | 四虎永久在线精品免费网址 | 天下第一社区视频www日本 | 无码国产色欲xxxxx视频 | 精品久久综合1区2区3区激情 | 亚洲а∨天堂久久精品2021 | 精品国产青草久久久久福利 | 在线亚洲高清揄拍自拍一品区 | 98国产精品综合一区二区三区 | 无码人妻丰满熟妇区五十路百度 | 亚洲欧美日韩成人高清在线一区 | 久久综合色之久久综合 | 免费无码午夜福利片69 | 色妞www精品免费视频 | 国产激情综合五月久久 | 久久99久久99精品中文字幕 | 性欧美牲交xxxxx视频 | 亚欧洲精品在线视频免费观看 | 欧美丰满熟妇xxxx性ppx人交 | 久久久久亚洲精品男人的天堂 | 秋霞成人午夜鲁丝一区二区三区 | 免费中文字幕日韩欧美 | 曰韩少妇内射免费播放 | 国产精品人妻一区二区三区四 | 国产成人无码a区在线观看视频app | 丰满岳乱妇在线观看中字无码 | 欧洲欧美人成视频在线 | 内射后入在线观看一区 | 日日天干夜夜狠狠爱 | 熟妇激情内射com | 无遮无挡爽爽免费视频 | 日本一本二本三区免费 | 国内少妇偷人精品视频免费 | 免费观看激色视频网站 | 老熟女乱子伦 | 亚洲毛片av日韩av无码 | 秋霞成人午夜鲁丝一区二区三区 | 婷婷六月久久综合丁香 | 国产精品内射视频免费 | 久久久久亚洲精品中文字幕 | 偷窥日本少妇撒尿chinese | 国产亚洲日韩欧美另类第八页 | av小次郎收藏 | 乱人伦中文视频在线观看 | 四虎国产精品一区二区 | 欧美国产日产一区二区 | 麻豆人妻少妇精品无码专区 | 欧美老妇交乱视频在线观看 | 成人性做爰aaa片免费看 | 久久无码中文字幕免费影院蜜桃 | 老熟女重囗味hdxx69 | 麻豆精产国品 | 国产人妖乱国产精品人妖 | 精品无人国产偷自产在线 | 欧美zoozzooz性欧美 | 好爽又高潮了毛片免费下载 | 成 人 网 站国产免费观看 | 欧美成人高清在线播放 | 久久亚洲a片com人成 | 亚洲一区二区三区在线观看网站 | yw尤物av无码国产在线观看 | 国产精华av午夜在线观看 | 久久久久久亚洲精品a片成人 | 国产莉萝无码av在线播放 | 少妇久久久久久人妻无码 | 国产极品美女高潮无套在线观看 | 激情内射亚州一区二区三区爱妻 | 丰满少妇弄高潮了www | 国产午夜无码视频在线观看 | 国产xxx69麻豆国语对白 | 亚洲区欧美区综合区自拍区 | 亚洲精品久久久久avwww潮水 | 亚洲精品国产第一综合99久久 | 女人高潮内射99精品 | 亚洲国产成人a精品不卡在线 | 一本无码人妻在中文字幕免费 | 红桃av一区二区三区在线无码av | 久久无码人妻影院 | 蜜桃视频韩日免费播放 | 天天摸天天透天天添 | 久久久久人妻一区精品色欧美 | 欧美成人高清在线播放 | 欧美亚洲国产一区二区三区 | 少妇久久久久久人妻无码 | 国产午夜亚洲精品不卡下载 | 国产综合在线观看 | 在教室伦流澡到高潮hnp视频 | 欧美丰满熟妇xxxx性ppx人交 | 天天做天天爱天天爽综合网 | 中文字幕无码av波多野吉衣 | 国产办公室秘书无码精品99 | 久久亚洲中文字幕精品一区 | 成熟女人特级毛片www免费 | 精品久久久久久人妻无码中文字幕 | 在线观看免费人成视频 | 小泽玛莉亚一区二区视频在线 | 最新国产麻豆aⅴ精品无码 | 精品国产一区二区三区四区 | 两性色午夜视频免费播放 | 国产性生交xxxxx无码 | 亚洲精品成人av在线 | 亚洲日韩av片在线观看 | 久久亚洲日韩精品一区二区三区 | 国产99久久精品一区二区 | 久久精品成人欧美大片 | 四虎国产精品免费久久 | 少妇性l交大片欧洲热妇乱xxx | 久久综合给合久久狠狠狠97色 | 亚洲欧美日韩综合久久久 | 欧美变态另类xxxx | 久久婷婷五月综合色国产香蕉 | 成年美女黄网站色大免费全看 | 性生交大片免费看l | 国产69精品久久久久app下载 | 免费无码一区二区三区蜜桃大 | 动漫av一区二区在线观看 | 天下第一社区视频www日本 | 色欲人妻aaaaaaa无码 | 国产福利视频一区二区 | 老头边吃奶边弄进去呻吟 | 亚洲中文字幕乱码av波多ji | 综合人妻久久一区二区精品 | 人人妻人人澡人人爽欧美一区九九 | 成在人线av无码免观看麻豆 | 大胆欧美熟妇xx | 强辱丰满人妻hd中文字幕 | 18禁止看的免费污网站 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 日日躁夜夜躁狠狠躁 | 中文字幕 亚洲精品 第1页 | 永久免费观看国产裸体美女 | 国产高清不卡无码视频 | 丰满少妇弄高潮了www | 亚洲中文字幕无码一久久区 | 岛国片人妻三上悠亚 | 国产亚洲精品久久久久久久久动漫 | 国产成人亚洲综合无码 | 妺妺窝人体色www婷婷 | 精品欧美一区二区三区久久久 | 国产suv精品一区二区五 | 久久无码人妻影院 | 樱花草在线播放免费中文 | 77777熟女视频在线观看 а天堂中文在线官网 | 国产精品人妻一区二区三区四 | 色一情一乱一伦一视频免费看 | 男人扒开女人内裤强吻桶进去 | 日本乱人伦片中文三区 | 久久精品成人欧美大片 | 性欧美大战久久久久久久 | 国产成人无码区免费内射一片色欲 | 国产又爽又黄又刺激的视频 | 撕开奶罩揉吮奶头视频 | 国产香蕉尹人视频在线 | 天堂久久天堂av色综合 | 波多野结衣av一区二区全免费观看 | 日产国产精品亚洲系列 | 国产成人无码av一区二区 | 亚洲午夜久久久影院 | 免费观看又污又黄的网站 | 国产精品欧美成人 | 国产精品a成v人在线播放 | 色五月五月丁香亚洲综合网 | 狠狠色欧美亚洲狠狠色www | 99久久精品午夜一区二区 | 男人的天堂2018无码 | 亚洲乱码国产乱码精品精 | 亚洲精品国产a久久久久久 | 国产精品亚洲一区二区三区喷水 | 国产午夜手机精彩视频 | 国产香蕉尹人综合在线观看 | 国产成人综合色在线观看网站 | 亚洲中文字幕成人无码 | 国内精品久久毛片一区二区 | 精品久久久无码人妻字幂 | 欧美乱妇无乱码大黄a片 | 欧美日韩人成综合在线播放 | 97夜夜澡人人双人人人喊 | 色婷婷香蕉在线一区二区 | 国产精品内射视频免费 | 一本久久伊人热热精品中文字幕 | 人人妻人人澡人人爽欧美精品 | 人妻与老人中文字幕 | 亚洲精品一区二区三区在线 | 99久久人妻精品免费二区 | 精品一二三区久久aaa片 | 一二三四社区在线中文视频 | 久久久久免费精品国产 | 欧美日韩一区二区免费视频 | 亚洲娇小与黑人巨大交 | 国产极品美女高潮无套在线观看 | 综合人妻久久一区二区精品 | 激情内射日本一区二区三区 | 日本免费一区二区三区最新 | 精品久久久久久亚洲精品 | 国产97人人超碰caoprom | 55夜色66夜色国产精品视频 | 色欲综合久久中文字幕网 | 亚洲成色在线综合网站 | 亚洲精品鲁一鲁一区二区三区 | 亚洲色成人中文字幕网站 | 久久www免费人成人片 | 欧美兽交xxxx×视频 | 色婷婷综合中文久久一本 | 纯爱无遮挡h肉动漫在线播放 | 无码人妻精品一区二区三区不卡 | 国产精品va在线观看无码 | 亚洲精品综合五月久久小说 | 欧美老妇交乱视频在线观看 | 18禁止看的免费污网站 | 久久精品99久久香蕉国产色戒 | 亚洲国产精品一区二区美利坚 | 国产69精品久久久久app下载 | 狂野欧美性猛xxxx乱大交 | 亚洲 另类 在线 欧美 制服 | 男女下面进入的视频免费午夜 | 在线看片无码永久免费视频 | 国产va免费精品观看 | 娇妻被黑人粗大高潮白浆 | 欧美成人午夜精品久久久 | 老子影院午夜精品无码 | 久久精品国产99精品亚洲 | 国产av人人夜夜澡人人爽麻豆 | 国产精品二区一区二区aⅴ污介绍 | 色欲久久久天天天综合网精品 | 女人和拘做爰正片视频 | 无码av免费一区二区三区试看 | 玩弄少妇高潮ⅹxxxyw | 男女爱爱好爽视频免费看 | 国产一区二区三区日韩精品 | 精品国产国产综合精品 | 国产免费久久久久久无码 | 国产精品无码一区二区三区不卡 | 精品aⅴ一区二区三区 | 欧洲精品码一区二区三区免费看 | 欧美xxxx黑人又粗又长 | 99精品视频在线观看免费 | 亚洲综合在线一区二区三区 | 东京热一精品无码av | 久久久精品欧美一区二区免费 | 精品少妇爆乳无码av无码专区 | 97精品国产97久久久久久免费 | 国产在热线精品视频 | 狠狠色丁香久久婷婷综合五月 | 亚洲精品欧美二区三区中文字幕 | 天堂在线观看www | 永久免费精品精品永久-夜色 | 成人免费视频在线观看 | 欧美激情内射喷水高潮 | 精品欧美一区二区三区久久久 | 女人和拘做爰正片视频 | 少妇性l交大片欧洲热妇乱xxx | 久久天天躁狠狠躁夜夜免费观看 | 又粗又大又硬又长又爽 | 久久人人97超碰a片精品 | 免费看男女做好爽好硬视频 | 国产精品无码永久免费888 | 黑人巨大精品欧美黑寡妇 | 97色伦图片97综合影院 | 久久久久久九九精品久 | 300部国产真实乱 | 国产麻豆精品一区二区三区v视界 | a片免费视频在线观看 | 亚洲乱码国产乱码精品精 | 国产无套粉嫩白浆在线 | 在线a亚洲视频播放在线观看 | 色偷偷人人澡人人爽人人模 | 日本护士毛茸茸高潮 | 无码人妻精品一区二区三区下载 | 免费中文字幕日韩欧美 | 国产无套内射久久久国产 | 国产成人精品优优av | 国产亚洲精品久久久久久 | 久久精品人妻少妇一区二区三区 | 强伦人妻一区二区三区视频18 | ass日本丰满熟妇pics | 国产免费无码一区二区视频 | av小次郎收藏 | 亚洲成av人片在线观看无码不卡 | 久久99精品久久久久久动态图 | 亚洲欧美国产精品久久 | 国产凸凹视频一区二区 | 午夜精品久久久久久久 | av在线亚洲欧洲日产一区二区 | 免费中文字幕日韩欧美 | 极品尤物被啪到呻吟喷水 | 日韩少妇内射免费播放 | 中文字幕人妻无码一区二区三区 | 国产黄在线观看免费观看不卡 | 无码帝国www无码专区色综合 | 婷婷六月久久综合丁香 | 久久久国产精品无码免费专区 | 天堂亚洲2017在线观看 | 国产精品亚洲综合色区韩国 | 永久免费观看美女裸体的网站 | 亚洲欧美国产精品久久 | 成人免费视频视频在线观看 免费 | 午夜肉伦伦影院 | 亚洲精品国偷拍自产在线观看蜜桃 | 亚洲成av人在线观看网址 | 中文精品无码中文字幕无码专区 | 麻豆蜜桃av蜜臀av色欲av | 国产亚洲欧美日韩亚洲中文色 | 波多野结衣av一区二区全免费观看 | 亚洲精品中文字幕久久久久 | 扒开双腿吃奶呻吟做受视频 | 无码人妻精品一区二区三区下载 | 亚洲成在人网站无码天堂 | 国产亚洲精品久久久ai换 | 东京无码熟妇人妻av在线网址 | 欧美人与善在线com | 国产av剧情md精品麻豆 | 久久久久久久人妻无码中文字幕爆 | 国内精品人妻无码久久久影院 | 色窝窝无码一区二区三区色欲 | 国产一区二区不卡老阿姨 | 俺去俺来也www色官网 | 久久久久国色av免费观看性色 | 精品国产精品久久一区免费式 | 国产69精品久久久久app下载 | 国产精品久久久午夜夜伦鲁鲁 | 狠狠色噜噜狠狠狠7777奇米 | 激情国产av做激情国产爱 | 久久综合九色综合97网 | 国产亚洲欧美日韩亚洲中文色 | 日日摸天天摸爽爽狠狠97 | 清纯唯美经典一区二区 | 欧洲精品码一区二区三区免费看 | 成人性做爰aaa片免费看 | 国产av一区二区精品久久凹凸 | 兔费看少妇性l交大片免费 | 国产特级毛片aaaaaaa高清 | 亚洲日韩av一区二区三区中文 | 十八禁视频网站在线观看 | 国产亚洲日韩欧美另类第八页 | 狠狠色色综合网站 | 色综合久久88色综合天天 | 国产av人人夜夜澡人人爽麻豆 | 中文字幕无码热在线视频 | 野狼第一精品社区 | 久久精品国产99精品亚洲 | 久久综合激激的五月天 | 日韩亚洲欧美中文高清在线 | 一本大道久久东京热无码av | 国产午夜福利100集发布 | 狂野欧美性猛xxxx乱大交 | 九九热爱视频精品 | 亚洲人交乣女bbw | 日韩视频 中文字幕 视频一区 | 国产97色在线 | 免 | 性生交大片免费看女人按摩摩 | 在教室伦流澡到高潮hnp视频 | 亚洲色大成网站www国产 | 亚洲一区二区三区在线观看网站 | 国产精品欧美成人 | 成 人 免费观看网站 | 狠狠色丁香久久婷婷综合五月 | 天天拍夜夜添久久精品 | 熟女俱乐部五十路六十路av | 激情爆乳一区二区三区 | 日韩亚洲欧美精品综合 | 日韩欧美成人免费观看 | 亚洲va欧美va天堂v国产综合 | 人人爽人人澡人人人妻 | 精品人妻人人做人人爽夜夜爽 | a在线观看免费网站大全 | 久久久婷婷五月亚洲97号色 | 亚洲精品国产第一综合99久久 | 98国产精品综合一区二区三区 | 久久99精品国产麻豆 | 久久国产36精品色熟妇 | 一本一道久久综合久久 | 国产va免费精品观看 | 欧美一区二区三区视频在线观看 | 久久久久亚洲精品男人的天堂 | 亚洲精品综合五月久久小说 | 3d动漫精品啪啪一区二区中 | 国产人妻精品一区二区三区不卡 | 蜜桃无码一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 国产9 9在线 | 中文 | 久久久久久久女国产乱让韩 | 亚洲精品中文字幕乱码 | 永久免费观看美女裸体的网站 | 少妇人妻av毛片在线看 | 欧美精品无码一区二区三区 | 亚洲欧美中文字幕5发布 | 成人亚洲精品久久久久 | 图片区 小说区 区 亚洲五月 | 无码精品国产va在线观看dvd | 久久 国产 尿 小便 嘘嘘 | 精品国产一区二区三区四区在线看 | 亚洲国产av精品一区二区蜜芽 | 老太婆性杂交欧美肥老太 | 国产女主播喷水视频在线观看 | 日韩欧美群交p片內射中文 | 国产精品久久久久久久影院 | 少妇被粗大的猛进出69影院 | 伊人久久大香线蕉av一区二区 | 亚洲欧美国产精品专区久久 | 国产亚洲精品久久久久久国模美 | 丝袜 中出 制服 人妻 美腿 | 亚洲码国产精品高潮在线 | 水蜜桃色314在线观看 | 中文字幕无码人妻少妇免费 | 免费人成网站视频在线观看 | 少妇性荡欲午夜性开放视频剧场 | 成人片黄网站色大片免费观看 | 国产精品18久久久久久麻辣 | 性欧美疯狂xxxxbbbb | 日本在线高清不卡免费播放 | 国产在热线精品视频 | 啦啦啦www在线观看免费视频 | 国产精品资源一区二区 | 大肉大捧一进一出好爽视频 | 成人片黄网站色大片免费观看 | www一区二区www免费 | 亚洲毛片av日韩av无码 | 色噜噜亚洲男人的天堂 | 亚洲欧美日韩成人高清在线一区 | 日韩精品a片一区二区三区妖精 | 亚洲色大成网站www国产 | 给我免费的视频在线观看 | 蜜桃臀无码内射一区二区三区 | 亚洲国产精品一区二区美利坚 | 日韩精品乱码av一区二区 | 国产香蕉尹人视频在线 | 一本加勒比波多野结衣 | 自拍偷自拍亚洲精品10p | 国产精品久久久久久久9999 | 国产精品对白交换视频 | 成人毛片一区二区 | 一个人免费观看的www视频 | 人妻少妇精品无码专区二区 | 波多野42部无码喷潮在线 | 青春草在线视频免费观看 | 又黄又爽又色的视频 | 久久精品国产一区二区三区肥胖 | 日韩精品乱码av一区二区 | 国产精品美女久久久久av爽李琼 | 久激情内射婷内射蜜桃人妖 | 色窝窝无码一区二区三区色欲 | 日日鲁鲁鲁夜夜爽爽狠狠 | 欧美精品无码一区二区三区 | 成人无码影片精品久久久 | 又粗又大又硬毛片免费看 | 日韩欧美中文字幕在线三区 | 夜夜影院未满十八勿进 | 久久精品女人天堂av免费观看 | 国产美女极度色诱视频www | 麻豆果冻传媒2021精品传媒一区下载 | 国产成人久久精品流白浆 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲国产精品一区二区第一页 | 天堂久久天堂av色综合 | 欧美日韩综合一区二区三区 | 亚洲一区二区观看播放 | 精品国产福利一区二区 | 欧美日韩一区二区免费视频 | 无码福利日韩神码福利片 | 熟女少妇人妻中文字幕 | 亚洲成av人片天堂网无码】 | 国产精品毛多多水多 | 欧洲美熟女乱又伦 | 午夜精品久久久久久久久 | 精品无码国产自产拍在线观看蜜 | 国产九九九九九九九a片 | 国产亚av手机在线观看 | 国产精品怡红院永久免费 | 国产av一区二区三区最新精品 | 色婷婷av一区二区三区之红樱桃 | 久久伊人色av天堂九九小黄鸭 | 成人综合网亚洲伊人 | 国产亚洲精品久久久闺蜜 | 思思久久99热只有频精品66 | 四虎永久在线精品免费网址 | 蜜桃无码一区二区三区 | 亚洲区小说区激情区图片区 | 亚洲精品国产品国语在线观看 | 久久人人爽人人人人片 | 久久精品国产99精品亚洲 | 国产香蕉97碰碰久久人人 | 在线看片无码永久免费视频 | 人妻aⅴ无码一区二区三区 | 国产亚洲美女精品久久久2020 | 久久综合狠狠综合久久综合88 | 未满成年国产在线观看 | 性做久久久久久久久 | 在线视频网站www色 | 日韩无套无码精品 | 国产精品亚洲а∨无码播放麻豆 | 欧美阿v高清资源不卡在线播放 | 欧美精品一区二区精品久久 | 无码任你躁久久久久久久 | 狠狠色色综合网站 | 97se亚洲精品一区 | 粗大的内捧猛烈进出视频 | 亚洲国产欧美日韩精品一区二区三区 | 俄罗斯老熟妇色xxxx | 蜜臀av在线观看 在线欧美精品一区二区三区 | 中文无码伦av中文字幕 | 精品国产aⅴ无码一区二区 | 国产婷婷色一区二区三区在线 | 国产精品对白交换视频 | 人人澡人人妻人人爽人人蜜桃 | 久久精品中文字幕一区 | 无码人妻精品一区二区三区下载 | 色欲综合久久中文字幕网 | 国产午夜视频在线观看 | 国产精品办公室沙发 | 正在播放老肥熟妇露脸 | 国产亚洲美女精品久久久2020 | 在线精品亚洲一区二区 | 熟妇人妻无码xxx视频 | 最近免费中文字幕中文高清百度 | 51国偷自产一区二区三区 | 国产亚洲精品久久久久久国模美 | 成人精品一区二区三区中文字幕 | 午夜不卡av免费 一本久久a久久精品vr综合 | 正在播放老肥熟妇露脸 | 狠狠综合久久久久综合网 | 久久精品人人做人人综合试看 | 丰满少妇人妻久久久久久 | 天天躁日日躁狠狠躁免费麻豆 | 亚洲中文字幕乱码av波多ji | 一本久道久久综合狠狠爱 | 久久综合狠狠综合久久综合88 | 色五月丁香五月综合五月 | 亚洲另类伦春色综合小说 | 欧美精品无码一区二区三区 | 日本高清一区免费中文视频 | 亚洲精品久久久久久久久久久 | 97无码免费人妻超级碰碰夜夜 | 亚洲综合无码久久精品综合 | 欧美xxxxx精品 | 男女下面进入的视频免费午夜 | 中文精品久久久久人妻不卡 | 国产亲子乱弄免费视频 | 人妻有码中文字幕在线 | 无码国模国产在线观看 | 好男人www社区 | 午夜肉伦伦影院 | 欧美性猛交xxxx富婆 | 国产黑色丝袜在线播放 | 男女猛烈xx00免费视频试看 | 久久久久国色av免费观看性色 | 欧美日韩精品 | 玩弄中年熟妇正在播放 | 亚洲色欲色欲欲www在线 | 亚洲精品鲁一鲁一区二区三区 | 色诱久久久久综合网ywww | 亚洲国产精华液网站w | 久久婷婷五月综合色国产香蕉 | 亚洲男人av香蕉爽爽爽爽 | 亚洲欧美色中文字幕在线 | 久久综合给久久狠狠97色 | 国产精品免费大片 | 亚洲国产一区二区三区在线观看 | 国产精品毛片一区二区 | 久久无码中文字幕免费影院蜜桃 | 又大又硬又爽免费视频 | 日本一区二区更新不卡 | 男女爱爱好爽视频免费看 | 自拍偷自拍亚洲精品被多人伦好爽 | 人妻互换免费中文字幕 | 国产激情一区二区三区 | 三级4级全黄60分钟 | www国产亚洲精品久久网站 | 国产精品无码一区二区桃花视频 | 97人妻精品一区二区三区 | 久久亚洲中文字幕无码 | аⅴ资源天堂资源库在线 | 国产熟妇高潮叫床视频播放 | 激情内射日本一区二区三区 | 一本无码人妻在中文字幕免费 | 老子影院午夜精品无码 | 国产区女主播在线观看 | 领导边摸边吃奶边做爽在线观看 | 国产成人人人97超碰超爽8 | 精品亚洲成av人在线观看 | 97人妻精品一区二区三区 | 成人无码精品1区2区3区免费看 | 亚洲熟妇自偷自拍另类 | 国产精品视频免费播放 | 中文字幕亚洲情99在线 | 无码午夜成人1000部免费视频 | 亚洲经典千人经典日产 | 亚洲成a人一区二区三区 | 精品一区二区不卡无码av | 午夜嘿嘿嘿影院 | 东京一本一道一二三区 | 99久久无码一区人妻 | 水蜜桃av无码 | 免费观看激色视频网站 | 76少妇精品导航 | 男人扒开女人内裤强吻桶进去 | 亚洲色大成网站www | 久久久中文久久久无码 | 国产明星裸体无码xxxx视频 | 久久久久99精品国产片 | 日本一区二区三区免费播放 | 日日鲁鲁鲁夜夜爽爽狠狠 | 午夜不卡av免费 一本久久a久久精品vr综合 | 亲嘴扒胸摸屁股激烈网站 | 亚洲欧美国产精品专区久久 | 亚洲成a人片在线观看无码 | 国产精品人人妻人人爽 | 久热国产vs视频在线观看 | 成人亚洲精品久久久久软件 | 99久久精品国产一区二区蜜芽 | 亚洲欧洲中文日韩av乱码 | 四虎国产精品免费久久 | 国产莉萝无码av在线播放 | 装睡被陌生人摸出水好爽 | 又色又爽又黄的美女裸体网站 | 人人妻人人澡人人爽人人精品浪潮 | 国产成人精品久久亚洲高清不卡 | 国产在线aaa片一区二区99 | 亚洲天堂2017无码中文 | 人妻aⅴ无码一区二区三区 | 无码福利日韩神码福利片 | 亚洲精品鲁一鲁一区二区三区 | 亚洲精品国产品国语在线观看 | 亚洲成av人在线观看网址 | 国产一区二区不卡老阿姨 | 国产肉丝袜在线观看 | 小泽玛莉亚一区二区视频在线 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 波多野结衣高清一区二区三区 | 久久久久久亚洲精品a片成人 | 人妻有码中文字幕在线 | 人妻无码αv中文字幕久久琪琪布 | 少妇被黑人到高潮喷出白浆 | 性啪啪chinese东北女人 | 国产黄在线观看免费观看不卡 | 日本熟妇乱子伦xxxx | 奇米影视7777久久精品人人爽 | 亚洲区欧美区综合区自拍区 | 亚洲国产一区二区三区在线观看 | 国产日产欧产精品精品app | 久久久成人毛片无码 | 久久人人爽人人人人片 | 中文字幕乱码人妻二区三区 | 亚洲国产精品美女久久久久 | 少妇无码一区二区二三区 | 成人亚洲精品久久久久 | 老熟妇乱子伦牲交视频 | 成熟人妻av无码专区 | 樱花草在线社区www | 亚洲成a人片在线观看无码3d | 欧美自拍另类欧美综合图片区 | 亚洲中文字幕av在天堂 | 丰满人妻翻云覆雨呻吟视频 | 高潮毛片无遮挡高清免费 | 久久97精品久久久久久久不卡 | 亚洲人成影院在线无码按摩店 | 暴力强奷在线播放无码 | 色婷婷久久一区二区三区麻豆 | 国产成人无码av片在线观看不卡 | 中文字幕无码av波多野吉衣 | 亚洲乱码日产精品bd | 欧美丰满熟妇xxxx | 国产av剧情md精品麻豆 | 久久久国产精品无码免费专区 | 一本大道久久东京热无码av | 少妇性俱乐部纵欲狂欢电影 | www国产亚洲精品久久久日本 | 鲁大师影院在线观看 | 国产精品亚洲а∨无码播放麻豆 | 大肉大捧一进一出好爽视频 | 性开放的女人aaa片 | 国产深夜福利视频在线 | 无人区乱码一区二区三区 | 性啪啪chinese东北女人 | 又粗又大又硬又长又爽 | 给我免费的视频在线观看 | 日日摸夜夜摸狠狠摸婷婷 | 男女爱爱好爽视频免费看 | 久久熟妇人妻午夜寂寞影院 | 人人妻人人澡人人爽欧美一区 | 人人澡人人透人人爽 | 红桃av一区二区三区在线无码av | 国产精品手机免费 | 国产精品无码成人午夜电影 | 久久精品99久久香蕉国产色戒 | 亚洲综合无码一区二区三区 | 日本xxxx色视频在线观看免费 | 日本免费一区二区三区最新 | 亚洲 欧美 激情 小说 另类 | 中文字幕无码av波多野吉衣 | 成年美女黄网站色大免费视频 | 97se亚洲精品一区 | 大胆欧美熟妇xx | 红桃av一区二区三区在线无码av | 丝袜人妻一区二区三区 | 欧美刺激性大交 | 亚洲 另类 在线 欧美 制服 | 国产成人精品一区二区在线小狼 | 久久国产精品偷任你爽任你 | 国产 精品 自在自线 | 久久久www成人免费毛片 | 国产口爆吞精在线视频 | 国产亚洲日韩欧美另类第八页 | 亚洲天堂2017无码 | 欧美野外疯狂做受xxxx高潮 | 亚洲aⅴ无码成人网站国产app | 欧美三级不卡在线观看 | 高清不卡一区二区三区 | 夫妻免费无码v看片 | 无码av中文字幕免费放 | 亚洲日本va中文字幕 | 国产无套粉嫩白浆在线 | 亚洲精品一区二区三区四区五区 | 丝袜 中出 制服 人妻 美腿 | 久久综合久久自在自线精品自 | 精品国产福利一区二区 | 亚洲成av人片在线观看无码不卡 | 日本高清一区免费中文视频 | 久久久国产精品无码免费专区 | 2020久久香蕉国产线看观看 | 99久久无码一区人妻 | 日本精品人妻无码免费大全 | 国产在热线精品视频 | 98国产精品综合一区二区三区 | 三级4级全黄60分钟 | 国产情侣作爱视频免费观看 | 最新国产麻豆aⅴ精品无码 | 色妞www精品免费视频 | 国产精品永久免费视频 | 国产精品无码一区二区桃花视频 | 无码人妻丰满熟妇区五十路百度 | 成人无码精品一区二区三区 | 老熟妇乱子伦牲交视频 | 久激情内射婷内射蜜桃人妖 | 亚洲国产精品美女久久久久 | 国产精品毛片一区二区 | 成人性做爰aaa片免费看 | 兔费看少妇性l交大片免费 | 强奷人妻日本中文字幕 | 一个人看的www免费视频在线观看 | 欧美野外疯狂做受xxxx高潮 | 国产精品自产拍在线观看 | 亚洲毛片av日韩av无码 | 亚洲精品国产精品乱码视色 | 成年美女黄网站色大免费全看 | 夜精品a片一区二区三区无码白浆 | 国产人成高清在线视频99最全资源 | 九九在线中文字幕无码 | 亚洲一区二区三区偷拍女厕 | 天堂а√在线中文在线 | 亚洲の无码国产の无码影院 | 久久五月精品中文字幕 | 四虎永久在线精品免费网址 | 日本爽爽爽爽爽爽在线观看免 | 少妇无码吹潮 | 亚洲人成网站免费播放 | 国产在线一区二区三区四区五区 | 青草视频在线播放 | 精品水蜜桃久久久久久久 | 奇米影视7777久久精品人人爽 | 成人亚洲精品久久久久软件 | 国产va免费精品观看 | 国产绳艺sm调教室论坛 | 激情五月综合色婷婷一区二区 | 乱码午夜-极国产极内射 | 中国女人内谢69xxxxxa片 | 中文字幕无码日韩欧毛 | 丰满人妻一区二区三区免费视频 | 国产精品久久久久久亚洲影视内衣 | 国内精品九九久久久精品 | 国产两女互慰高潮视频在线观看 | 性欧美牲交xxxxx视频 | 白嫩日本少妇做爰 | 亚洲精品久久久久avwww潮水 | 夜夜影院未满十八勿进 | 3d动漫精品啪啪一区二区中 | 亚洲一区二区三区 | 牲欲强的熟妇农村老妇女 | av无码电影一区二区三区 | 最近的中文字幕在线看视频 | 亚洲精品国产品国语在线观看 | 扒开双腿疯狂进出爽爽爽视频 | 一区二区传媒有限公司 | 国产在线精品一区二区三区直播 | 久久精品99久久香蕉国产色戒 | 牲交欧美兽交欧美 | 青草青草久热国产精品 | 久久99精品国产.久久久久 | 在线精品国产一区二区三区 | 久久五月精品中文字幕 | 国精产品一品二品国精品69xx | 欧美国产日产一区二区 | 国产精品美女久久久久av爽李琼 | 少妇无码av无码专区在线观看 | 亚洲成在人网站无码天堂 | 中文字幕av日韩精品一区二区 | 日韩无码专区 | 日日摸日日碰夜夜爽av | 日日橹狠狠爱欧美视频 | 18无码粉嫩小泬无套在线观看 | 草草网站影院白丝内射 | 高潮毛片无遮挡高清免费 | 亚洲一区二区三区含羞草 | 国产办公室秘书无码精品99 | 午夜福利一区二区三区在线观看 | 久久99国产综合精品 | 亚洲の无码国产の无码影院 | 国产熟女一区二区三区四区五区 | 欧美怡红院免费全部视频 | 成 人 免费观看网站 | 嫩b人妻精品一区二区三区 | 亚洲国产av精品一区二区蜜芽 | 任你躁国产自任一区二区三区 | 人人妻人人澡人人爽欧美一区九九 | 午夜不卡av免费 一本久久a久久精品vr综合 | 18禁黄网站男男禁片免费观看 | 欧洲美熟女乱又伦 | 成年女人永久免费看片 | 亚洲の无码国产の无码步美 | 久久国产精品二国产精品 | 日韩亚洲欧美精品综合 | 亚洲大尺度无码无码专区 | 久久精品视频在线看15 | 99在线 | 亚洲 | 国产精品嫩草久久久久 | 国产电影无码午夜在线播放 | 中文字幕精品av一区二区五区 | 国产超碰人人爽人人做人人添 | a国产一区二区免费入口 | 十八禁真人啪啪免费网站 | 午夜无码人妻av大片色欲 | 一本色道久久综合狠狠躁 | 18精品久久久无码午夜福利 | 人人妻人人澡人人爽人人精品浪潮 | 久久综合给久久狠狠97色 | a片免费视频在线观看 | 熟女体下毛毛黑森林 | 无码人妻精品一区二区三区不卡 | 久久99精品久久久久久 | 少妇邻居内射在线 | 野狼第一精品社区 | 精品久久综合1区2区3区激情 | 永久黄网站色视频免费直播 | 国产精品高潮呻吟av久久4虎 | 久久精品人妻少妇一区二区三区 | 老熟妇乱子伦牲交视频 | 久久综合久久自在自线精品自 | 中文字幕无码热在线视频 | 99久久99久久免费精品蜜桃 | 日韩精品无码免费一区二区三区 | www国产亚洲精品久久网站 | 无码吃奶揉捏奶头高潮视频 | 任你躁国产自任一区二区三区 | 大胆欧美熟妇xx | 国产熟妇高潮叫床视频播放 | 精品久久久无码中文字幕 | 色综合久久网 | 人人妻人人澡人人爽精品欧美 | 国产亚洲欧美在线专区 | 国产精品国产三级国产专播 | 激情内射日本一区二区三区 | 亚洲中文字幕成人无码 | 俺去俺来也在线www色官网 | 美女极度色诱视频国产 | 日本在线高清不卡免费播放 | 久久99精品久久久久久动态图 | 国产高清av在线播放 | 激情内射日本一区二区三区 | 99久久久无码国产精品免费 | 国产在线精品一区二区高清不卡 | 对白脏话肉麻粗话av | 国产超级va在线观看视频 | 国产真人无遮挡作爱免费视频 | 99国产欧美久久久精品 | 又黄又爽又色的视频 | 18黄暴禁片在线观看 | 玩弄中年熟妇正在播放 | 国产免费久久久久久无码 | 日韩无套无码精品 | 偷窥日本少妇撒尿chinese | 久久人人爽人人爽人人片av高清 | 国产精品永久免费视频 | 激情内射亚州一区二区三区爱妻 | 国产精品爱久久久久久久 | 亚洲七七久久桃花影院 | 色欲综合久久中文字幕网 | 国产suv精品一区二区五 | 精品厕所偷拍各类美女tp嘘嘘 | 蜜桃视频插满18在线观看 | 中文字幕人妻无码一夲道 | 久久精品人人做人人综合 | √8天堂资源地址中文在线 | 亚洲欧美日韩国产精品一区二区 | 毛片内射-百度 | 国产在线精品一区二区三区直播 | 欧美阿v高清资源不卡在线播放 | 国产av人人夜夜澡人人爽麻豆 | 国产精品无套呻吟在线 | 日韩人妻系列无码专区 | 国产精品成人av在线观看 | 人人澡人人妻人人爽人人蜜桃 | 成人一区二区免费视频 | 人人妻人人澡人人爽精品欧美 | 性欧美熟妇videofreesex | 性欧美大战久久久久久久 | 欧美变态另类xxxx | 日产精品高潮呻吟av久久 | 无码成人精品区在线观看 | 我要看www免费看插插视频 | 国产成人精品必看 | 特黄特色大片免费播放器图片 | 欧美日韩久久久精品a片 | 国产免费久久精品国产传媒 | 一区二区三区乱码在线 | 欧洲 | 大色综合色综合网站 | 捆绑白丝粉色jk震动捧喷白浆 | 精品夜夜澡人妻无码av蜜桃 | 日本欧美一区二区三区乱码 | 人妻与老人中文字幕 | 日韩精品乱码av一区二区 | 亚洲国产av美女网站 | 久久99久久99精品中文字幕 | 欧美猛少妇色xxxxx | 在线播放免费人成毛片乱码 | 中文字幕无码日韩专区 | 成人性做爰aaa片免费看不忠 | 国产无av码在线观看 | 无码乱肉视频免费大全合集 | 亚洲 a v无 码免 费 成 人 a v | 精品亚洲成av人在线观看 | 牲欲强的熟妇农村老妇女视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | 午夜无码区在线观看 | 亚洲精品国产a久久久久久 | 一个人免费观看的www视频 | 97久久国产亚洲精品超碰热 | 欧美日韩在线亚洲综合国产人 | 久久精品国产大片免费观看 | 精品欧洲av无码一区二区三区 | 午夜福利试看120秒体验区 | 夜夜高潮次次欢爽av女 | 久久国语露脸国产精品电影 | 欧美三级不卡在线观看 | 亚洲精品久久久久久久久久久 | 日韩精品a片一区二区三区妖精 | 中文字幕+乱码+中文字幕一区 | 国产口爆吞精在线视频 | 丰满人妻被黑人猛烈进入 | 色综合久久久无码中文字幕 | 亚洲男人av香蕉爽爽爽爽 | 婷婷六月久久综合丁香 | 奇米影视7777久久精品人人爽 | 亚洲国产欧美日韩精品一区二区三区 | 一二三四在线观看免费视频 | 国产明星裸体无码xxxx视频 | 久久久中文久久久无码 | 色一情一乱一伦一视频免费看 | 精品偷拍一区二区三区在线看 | 久久久精品成人免费观看 | 婷婷六月久久综合丁香 | 少妇被粗大的猛进出69影院 | 色婷婷久久一区二区三区麻豆 | 国产精品人人妻人人爽 | 亚洲成av人片在线观看无码不卡 | 亚洲综合无码久久精品综合 | 午夜熟女插插xx免费视频 | 人人妻在人人 | 久久人人97超碰a片精品 | 在线观看免费人成视频 | 中文无码伦av中文字幕 | 亚洲成av人综合在线观看 | 亚洲精品久久久久久久久久久 | 大乳丰满人妻中文字幕日本 | 国产成人无码av在线影院 | 亚洲大尺度无码无码专区 | 西西人体www44rt大胆高清 | 国产精品美女久久久网av | 欧美国产日产一区二区 | 国产精品久久久一区二区三区 | 亚洲一区二区三区国产精华液 | 天海翼激烈高潮到腰振不止 | 无码毛片视频一区二区本码 | 久久精品国产一区二区三区肥胖 | 国产亚洲精品久久久ai换 | 精品厕所偷拍各类美女tp嘘嘘 | 久久国产36精品色熟妇 | 午夜无码区在线观看 | 久久午夜无码鲁丝片 | 久久99国产综合精品 | 欧美熟妇另类久久久久久多毛 | 国产又粗又硬又大爽黄老大爷视 | 成年美女黄网站色大免费全看 | 亚洲欧洲日本无在线码 | 国产精品99久久精品爆乳 | 亚洲区小说区激情区图片区 | 亚洲欧洲中文日韩av乱码 | 成 人 免费观看网站 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 免费无码的av片在线观看 | 国産精品久久久久久久 | 久久精品人人做人人综合试看 | 久久精品一区二区三区四区 | av无码久久久久不卡免费网站 | 欧美zoozzooz性欧美 | 久久精品女人天堂av免费观看 | 性做久久久久久久久 | 国精产品一品二品国精品69xx | 久久久久久国产精品无码下载 | 亚洲日韩精品欧美一区二区 | 撕开奶罩揉吮奶头视频 | 国产熟妇另类久久久久 | 99久久无码一区人妻 | 亚洲日韩av一区二区三区四区 | 亚洲成色在线综合网站 | 久精品国产欧美亚洲色aⅴ大片 | 国产亚洲精品久久久ai换 | 成年美女黄网站色大免费视频 | 欧美三级a做爰在线观看 | 成人免费无码大片a毛片 | 天天躁日日躁狠狠躁免费麻豆 | 久久久久久久人妻无码中文字幕爆 | 久久精品中文闷骚内射 | 天堂а√在线地址中文在线 | 男女爱爱好爽视频免费看 | 国产成人无码a区在线观看视频app | www国产精品内射老师 | 亚欧洲精品在线视频免费观看 | 97无码免费人妻超级碰碰夜夜 | 国产无遮挡又黄又爽免费视频 | 青青草原综合久久大伊人精品 | 中文亚洲成a人片在线观看 | 精品国产一区av天美传媒 | 亚洲国产成人a精品不卡在线 | 无码人妻丰满熟妇区五十路百度 | 一本久久伊人热热精品中文字幕 | 99国产欧美久久久精品 | 精品亚洲成av人在线观看 | 免费播放一区二区三区 | 国语精品一区二区三区 | 国产成人综合在线女婷五月99播放 | 东京热一精品无码av | 狠狠色色综合网站 | 亚洲精品一区国产 | 欧美 亚洲 国产 另类 | 亚洲另类伦春色综合小说 | 成人精品视频一区二区 | 国产免费久久精品国产传媒 | 亚洲中文字幕久久无码 | 久久无码中文字幕免费影院蜜桃 | 丰满护士巨好爽好大乳 | 性做久久久久久久久 | 国产综合久久久久鬼色 | 免费中文字幕日韩欧美 | 亚洲综合在线一区二区三区 | 98国产精品综合一区二区三区 | 国产乱人偷精品人妻a片 | 国内丰满熟女出轨videos | 狂野欧美激情性xxxx | av在线亚洲欧洲日产一区二区 | 久久www免费人成人片 | 久久97精品久久久久久久不卡 | 色偷偷人人澡人人爽人人模 | 狠狠躁日日躁夜夜躁2020 | 亚洲欧美综合区丁香五月小说 | 人妻无码久久精品人妻 | 国产农村乱对白刺激视频 | 亚洲日韩一区二区三区 | 久久久中文字幕日本无吗 | 久久国产精品_国产精品 | 一本大道久久东京热无码av | 亚洲男人av天堂午夜在 | 成人动漫在线观看 | 无码吃奶揉捏奶头高潮视频 | 日本va欧美va欧美va精品 | 亚洲精品一区二区三区大桥未久 | 激情内射亚州一区二区三区爱妻 | 亚洲成a人片在线观看日本 | 国产真实乱对白精彩久久 | 粗大的内捧猛烈进出视频 | 67194成是人免费无码 | 久久久久久av无码免费看大片 | 在线观看欧美一区二区三区 | 国产精品手机免费 | 亚洲精品久久久久avwww潮水 | 亚洲中文字幕在线无码一区二区 | 午夜福利不卡在线视频 | 国产成人精品视频ⅴa片软件竹菊 | 国产精品多人p群无码 | 西西人体www44rt大胆高清 | 日韩人妻系列无码专区 | 四虎影视成人永久免费观看视频 | 老司机亚洲精品影院 | 亚洲色成人中文字幕网站 | 国产av人人夜夜澡人人爽麻豆 | 国产精品久久久av久久久 | 日日麻批免费40分钟无码 | 国产人成高清在线视频99最全资源 | 亚洲人亚洲人成电影网站色 | 九九在线中文字幕无码 | 人妻与老人中文字幕 | 国产亚洲精品久久久久久 | 樱花草在线播放免费中文 | 自拍偷自拍亚洲精品被多人伦好爽 | 精品aⅴ一区二区三区 | 国产亚洲精品久久久久久 | 最近的中文字幕在线看视频 | 亚洲乱码国产乱码精品精 | 久久人人爽人人爽人人片av高清 | 2020久久香蕉国产线看观看 | 国产av一区二区精品久久凹凸 | 精品久久久无码人妻字幂 | 夜夜影院未满十八勿进 | 精品一区二区三区波多野结衣 | 97人妻精品一区二区三区 | 乱码午夜-极国产极内射 | 国产片av国语在线观看 | 久久久久久久人妻无码中文字幕爆 | 波多野结衣aⅴ在线 | 麻豆国产97在线 | 欧洲 | 国产精品久久久av久久久 | 精品久久久久久人妻无码中文字幕 | 国产成人人人97超碰超爽8 | 国产色精品久久人妻 | √天堂中文官网8在线 | 国产激情无码一区二区 | av无码不卡在线观看免费 | 成人片黄网站色大片免费观看 | а√资源新版在线天堂 | 亚洲日韩一区二区三区 | 中文字幕人妻无码一区二区三区 | 国产成人综合在线女婷五月99播放 | 在线观看免费人成视频 | 欧美熟妇另类久久久久久多毛 | 久久99精品国产麻豆 | 东京热男人av天堂 | a片免费视频在线观看 | 日韩亚洲欧美中文高清在线 | 国产精品二区一区二区aⅴ污介绍 | a在线亚洲男人的天堂 | 午夜嘿嘿嘿影院 | 成人一在线视频日韩国产 | 人人妻人人澡人人爽欧美一区 | 国产精品无套呻吟在线 | 国产亚av手机在线观看 | 色欲久久久天天天综合网精品 | 97夜夜澡人人双人人人喊 | 免费看少妇作爱视频 | 亚欧洲精品在线视频免费观看 | 日韩成人一区二区三区在线观看 |