精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

WebSocket實現(xiàn)原理

開發(fā)
WebSocket 和 Socket 雖然名稱上很像,但兩者是完全不同的東西, WebSocket 是建立在 TCP/IP 協(xié)議之上,屬于應用層的協(xié)議,而 Socket 是在應用層和傳輸層中的一個抽象層,它是將 TCP/IP 層的復雜操作抽象成幾個簡單的接口來提供給應用層調用。

背景

之前我們將 CocoaAsyncSocket 作為底層實現(xiàn),在其上面封裝了一套 Socket 通信機制以及業(yè)務接口,最近我們開始研究 WebSocket ,并用來替換掉原先的 CocoaAsyncSocket ,簡單來說一下兩者的關系,WebSocket 和 Socket 雖然名稱上很像,但兩者是完全不同的東西, WebSocket 是建立在 TCP/IP 協(xié)議之上,屬于應用層的協(xié)議,而 Socket 是在應用層和傳輸層中的一個抽象層,它是將 TCP/IP 層的復雜操作抽象成幾個簡單的接口來提供給應用層調用。為什么要做這次替換呢?原因是我們服務端在做改造,同時網頁版 IM 已經使用了 WebSocket ,客戶端也采用的話對于服務端來說維護一套代碼會更好更方便,而且 WebSocket 在體積、實時性和擴展上都具有一定的優(yōu)勢。

WebSocket ***的協(xié)議是 13 RFC 6455 ,要理解 WebSocket 的實現(xiàn),一定要去理解它的協(xié)議!~

前言

WebSocket 的實現(xiàn)分為握手,數(shù)據(jù)發(fā)送/讀取,關閉連接。

這里首先放上一張我們組 @省長 (推薦大家去讀一讀省長的博客,干貨很多👍)整理出來的流程圖,方便大家去理解:

 

握手

握手要從請求頭去理解。

WebSocket 首先發(fā)起一個 HTTP 請求,在請求頭加上 Upgrade 字段,該字段用于改變 HTTP 協(xié)議版本或者是換用其他協(xié)議,這里我們把 Upgrade 的值設為 websocket ,將它升級為 WebSocket 協(xié)議。

同時要注意 Sec-WebSocket-Key 字段,它由客戶端生成并發(fā)給服務端,用于證明服務端接收到的是一個可受信的連接握手,可以幫助服務端排除自身接收到的由非 WebSocket 客戶端發(fā)起的連接,該值是一串隨機經過 base64 編碼的字符串。

  1. GET /chat HTTP/1.1 
  2.  
  3. Host: server.example.com 
  4.  
  5. Upgrade: websocket 
  6.  
  7. Connection: Upgrade 
  8.  
  9. Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 
  10.  
  11. Origin: http://example.com 
  12.  
  13. Sec-WebSocket-Protocol: chat, superchat 
  14.  
  15. Sec-WebSocket-Version: 13  

我們可以簡化請求頭,將請求以字符串方式發(fā)送出去,當然別忘了***的兩個空行作為包結束:

  1. const char * fmt = "GET %s HTTP/1.1\r\n" 
  2.  
  3. "Upgrade: websocket\r\n" 
  4.  
  5. "Connection: Upgrade\r\n" 
  6.  
  7. "Host: %s\r\n" 
  8.  
  9. "Sec-WebSocket-Key: %s\r\n" 
  10.  
  11. "Sec-WebSocket-Version: 13\r\n" 
  12.  
  13. "\r\n"
  14.  
  15. size = strlen(fmt) + strlen(path) + strlen(host) + strlen(ws->key); 
  16.  
  17. buf = (char *)malloc(size); 
  18.  
  19. sprintf(buf, fmt, path, host, ws->key); 
  20.  
  21. size = strlen(buf); 
  22.  
  23. nbytes = ws->io_send(ws, ws->context, buf, size);  

收到請求后,服務端也會做一次響應:

  1. HTTP/1.1 101 Switching Protocols 
  2.  
  3. Upgrade: websocket 
  4.  
  5. Connection: Upgrade 
  6.  
  7. Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=  

里面重要的是 Sec-WebSocket-Accept ,服務端通過從客戶端請求頭中讀取 Sec-WebSocket-Key 與一串全局唯一的標識字符串(俗稱魔串)“258EAFA5-E914-47DA- 95CA-C***B0DC85B11”做拼接,生成長度為160位的 SHA-1 字符串,然后進行 base64 編碼,作為 Sec-WebSocket-Accept 的值回傳給客戶端。

處理握手 HTTP 響應解析的時候,可以用 nodejs 的 http-paser ,解析方式也比較簡單,就是對頭信息的逐字讀取再處理,具體處理你可以看一下它的狀態(tài)機實現(xiàn)。解析完成后你需要對其內容進行解析,看返回是否正確,同時去管理你的握手狀態(tài)。

數(shù)據(jù)發(fā)送/讀取

數(shù)據(jù)的處理就要拿這個幀協(xié)議圖來說明了:

 

首先我們來看看數(shù)字的含義,數(shù)字表示位,0-7表示有8位,等于1個字節(jié)。

  1. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 

所以如果要組裝一個幀數(shù)據(jù)可以這樣子:

  1. char *rev = (rev *)malloc(4); 
  2.  
  3. rev[0] = (char)(0x81 & 0xff); 
  4.  
  5. rev[1] = 126 & 0x7f; 
  6.  
  7. rev[2] = 1; 
  8.  
  9. rev[3] = 0;  

ok,了解了幀數(shù)據(jù)的樣子,我們反過來去理解值對應的幀字段。

首先0x81是什么,這個是十六進制數(shù)據(jù),轉換成二進制就是1000 0001, 是一個字節(jié)的長度,也就是這一段里面每一位的值:

 

  • FIN 表示該幀是不是消息的***一幀,1表示結束,0表示還有下一幀。
  • RSV1, RSV2, RSV3 必須為0,除非擴展協(xié)商定義了一個非0的值,如果沒有定義非0值,且收到了非0的 RSV ,那么 WebSocket 的連接會失效。
  • opcode 用來描述 Payload data 的定義,如果收到了一個未知的 opcode ,同樣會使 WebSocket 連接失效,協(xié)議定義了以下值:
    • %x0 表示連續(xù)的幀
    • %x1 表示 text 幀
    • %x2 表示二進制幀
    • %x3-7 預留給非控制幀
    • %x8 表示關閉連接幀
    • %x9 表示 ping
    • %xA 表示 pong
    • %xB-F 預留給控制幀

0xff 作用就是取出需要的二進制值。

下面再來看126,126則表示的是 Payload len ,也就是 Payload 的長度:

 

  • MASK 表示Playload data 是否要加掩碼,如果設成1,則需要賦值 Masking-key 。所有從客戶端發(fā)到服務端的幀都要加掩碼
  • Playload len 表示 Payload 的長度,這里分為三種情況
    • 長度小于126,則只需要7位
    • 長度是126,則需要額外2個字節(jié)的大小,也就是 Extended payload length
    • 長度是127,則需要額外8個字節(jié)的大小,也就是 Extended payload length + Extended payload length continued ,Extended payload length 是2個字節(jié),Extended payload length continued 是6個字節(jié)
  • Playload len 則表示 Extension data 與 Application data 的和

而數(shù)據(jù)的發(fā)送和讀取就是對幀的封裝和解析。

數(shù)據(jù)發(fā)送:

  1. void ws__wrap_packet(_WS_IN websocket_t *ws, 
  2.  
  3. _WS_IN const char *payload, 
  4.  
  5. _WS_IN unsigned long long payload_size, 
  6.  
  7. _WS_IN int flags, 
  8.  
  9. _WS_OUT char** out
  10.  
  11. _WS_OUT uint64_t *out_size) { 
  12.  
  13.   
  14.  
  15. struct timeval tv; 
  16.  
  17. char mask[4]; 
  18.  
  19. unsigned int mask_int; 
  20.  
  21. unsigned int payload_len_bits; 
  22.  
  23. unsigned int payload_bit_offset = 6; 
  24.  
  25. unsigned int extend_payload_len_bits, i; 
  26.  
  27. unsigned long long frame_size; 
  28.  
  29.   
  30.  
  31. const int MASK_BIT_LEN = 4; 
  32.  
  33.   
  34.  
  35. gettimeofday(&tv, NULL); 
  36.  
  37. srand(tv.tv_usec * tv.tv_sec); 
  38.  
  39. mask_int = rand(); 
  40.  
  41. memcpy(mask, &mask_int, 4); 
  42.  
  43.   
  44.  
  45. /** 
  46.  
  47. * payload_len bits 
  48.  
  49. * ref to https://tools.ietf.org/html/rfc6455#section-5.2 
  50.  
  51. * If 0-125, that is the payload length 
  52.  
  53.  
  54. * If payload length is equals 126, the following 2 bytes interpreted as a 
  55.  
  56. * 16-bit unsigned integer are the payload length 
  57.  
  58.  
  59. * If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the 
  60.  
  61. * most significant bit MUST be 0) are the payload length. 
  62.  
  63. */ 
  64.  
  65. if (payload_size 125) { 
  66.  
  67. // consts of ((fin + rsv1/2/3 + opcode) + payload-len bits + mask bit len + payload len) 
  68.  
  69. extend_payload_len_bits = 0; 
  70.  
  71. frame_size = 1 + 1 + MASK_BIT_LEN + payload_size; 
  72.  
  73.   
  74.  
  75. payload_len_bits = payload_size; 
  76.  
  77. else if (payload_size > 125 && payload_size 0xffff) { 
  78.  
  79. extend_payload_len_bits = 2; 
  80.  
  81. // consts of ((fin + rsv1/2/3 + opcode) + payload-len bits + extend-payload-len bites + mask bit len + payload len) 
  82.  
  83. frame_size = 1 + 1 + extend_payload_len_bits + MASK_BIT_LEN + payload_size; 
  84.  
  85. payload_len_bits = 126; 
  86.  
  87.   
  88.  
  89. payload_bit_offset += extend_payload_len_bits; 
  90.  
  91. else if (payload_size > 0xffff && payload_size 0xffffffffffffffffLL) { 
  92.  
  93. extend_payload_len_bits = 8; 
  94.  
  95. // consts of ((fin + rsv1/2/3 + opcode) + payload-len bits + extend-payload-len bites + mask bit len + payload len) 
  96.  
  97. frame_size = 1 + 1 + extend_payload_len_bits + MASK_BIT_LEN + payload_size; 
  98.  
  99. payload_len_bits = 127; 
  100.  
  101. payload_bit_offset += extend_payload_len_bits; 
  102.  
  103. else { 
  104.  
  105. if (ws->error_cb) { 
  106.  
  107. ws_error_t *err = ws_new_error(WS_SEND_DATA_TOO_LARGE_ERR); 
  108.  
  109. ws->error_cb(ws, err); 
  110.  
  111. free(err); 
  112.  
  113.  
  114. return ; 
  115.  
  116.  
  117.   
  118.  
  119. *out_size = frame_size; 
  120.  
  121. char *data = (*out) = (char *)malloc(frame_size); 
  122.  
  123. char *buf_offset = data; 
  124.  
  125.   
  126.  
  127. bzero(data, frame_size); 
  128.  
  129. *data = flags & 0xff; 
  130.  
  131.   
  132.  
  133. buf_offset = data + 1; 
  134.  
  135.   
  136.  
  137. // set mask bit = 1 
  138.  
  139. *(buf_offset) = payload_len_bits | 0x80; //payload length with mask bit on 
  140.  
  141.   
  142.  
  143. buf_offset = data + 2; 
  144.  
  145. if (payload_len_bits == 126) { 
  146.  
  147. payload_size &= 0xffff; 
  148.  
  149. else if (payload_len_bits == 127) { 
  150.  
  151. payload_size &= 0xffffffffffffffffLL; 
  152.  
  153.  
  154.   
  155.  
  156. for (i = 0; i 
  157.  
  158. *(buf_offset + i) = *((char *)&payload_size + (extend_payload_len_bits - i - 1)); 
  159.  
  160.  
  161.   
  162.  
  163.   
  164.  
  165. /** 
  166.  
  167. * according to https://tools.ietf.org/html/rfc6455#section-5.3 
  168.  
  169.  
  170. * buf_offset is set to mask bit 
  171.  
  172. */ 
  173.  
  174. buf_offset = data + payload_bit_offset - 4; 
  175.  
  176. for (i = 0; i 4; i++) { 
  177.  
  178. *(buf_offset + i) = mask[i] & 0xff; 
  179.  
  180.  
  181.   
  182.  
  183. /** 
  184.  
  185. * mask the payload data 
  186.  
  187. */ 
  188.  
  189. buf_offset = data + payload_bit_offset; 
  190.  
  191. memcpy(buf_offset, payload, payload_size); 
  192.  
  193. mask_payload(mask, buf_offset, payload_size); 
  194.  
  195.  
  196.   
  197.  
  198. void mask_payload(char mask[4], char *payload, unsigned long long payload_size) { 
  199.  
  200. unsigned long long i; 
  201.  
  202. for(i = 0; i 
  203.  
  204. *(payload + i) ^= mask[i % 4] & 0xff; 
  205.  
  206.  
  207.  

數(shù)據(jù)解析:

  1. int ws_recv(websocket_t *ws) { 
  2.  
  3. if (ws->state 
  4.  
  5. return ws_do_handshake(ws); 
  6.  
  7.  
  8.   
  9.  
  10. int ret; 
  11.  
  12. while(true) { 
  13.  
  14. ret = ws__recv(ws); 
  15.  
  16. if (ret != OK) { 
  17.  
  18. break; 
  19.  
  20.  
  21.  
  22.   
  23.  
  24. return ret; 
  25.  
  26.  
  27.   
  28.  
  29. int ws__recv(websocket_t *ws) { 
  30.  
  31. if (ws->state 
  32.  
  33. return ws_do_handshake(ws); 
  34.  
  35.  
  36.   
  37.  
  38. int ret = OK, i; 
  39.  
  40. int state = ws->rd_state; 
  41.  
  42. char *rd_buf; 
  43.  
  44.   
  45.  
  46. switch(state) { 
  47.  
  48. case WS_READ_IDLE: { 
  49.  
  50. ret = ws__make_up(ws, 2); 
  51.  
  52. if (ret != OK) { 
  53.  
  54. return ret; 
  55.  
  56.  
  57.   
  58.  
  59. ws_frame_t * frame; 
  60.  
  61. if (ws->c_frame == NULL) { 
  62.  
  63. ws__append_frame(ws); 
  64.  
  65.  
  66. frame = ws->c_frame; 
  67.  
  68. rd_buf = ws->buf; 
  69.  
  70. frame->fin = (*(rd_buf) & 0x80) == 0x80 ? 1 : 0; 
  71.  
  72. frame->op_code = *(rd_buf) & 0x0fu; 
  73.  
  74. frame->payload_len = *(rd_buf + 1) & 0x7fu; 
  75.  
  76.   
  77.  
  78. if (frame->payload_len 126) { 
  79.  
  80. frame->payload_bit_offset = 2; 
  81.  
  82. ws->rd_state = WS_READ_PAYLOAD; 
  83.  
  84. else if (frame -> payload_len == 126) { 
  85.  
  86. frame->payload_bit_offset = 4; 
  87.  
  88. ws->rd_state = WS_READ_EXTEND_PAYLOAD_2_WORDS; 
  89.  
  90. else { 
  91.  
  92. frame->payload_bit_offset = 8; 
  93.  
  94. ws->rd_state = WS_READ_EXTEND_PAYLOAD_8_WORDS; 
  95.  
  96.  
  97.   
  98.  
  99. ws__reset_buf(ws, 2); 
  100.  
  101. break; 
  102.  
  103.  
  104. case WS_READ_EXTEND_PAYLOAD_2_WORDS: { 
  105.  
  106. #define PAYLOAD_LEN_BITS 2 
  107.  
  108. ret = ws__make_up(ws, PAYLOAD_LEN_BITS); 
  109.  
  110. if (ret != OK) { 
  111.  
  112. return ret; 
  113.  
  114.  
  115. rd_buf = ws->buf; 
  116.  
  117. ws_frame_t * frame = ws->c_frame; 
  118.  
  119.   
  120.  
  121. char *payload_len_bytes = (char *)&frame->payload_len; 
  122.  
  123. for (i = 0; i 
  124.  
  125. *(payload_len_bytes + i) = rd_buf[PAYLOAD_LEN_BITS - 1 - i]; 
  126.  
  127.  
  128.   
  129.  
  130. ws__reset_buf(ws, PAYLOAD_LEN_BITS); 
  131.  
  132. ws->rd_state = WS_READ_PAYLOAD; 
  133.  
  134. #undef PAYLOAD_LEN_BITS 
  135.  
  136. break; 
  137.  
  138.  
  139. case WS_READ_EXTEND_PAYLOAD_8_WORDS: { 
  140.  
  141. #define PAYLOAD_LEN_BITS 8 
  142.  
  143. ret = ws__make_up(ws, PAYLOAD_LEN_BITS); 
  144.  
  145. if (ret != OK) { 
  146.  
  147. return ret; 
  148.  
  149.  
  150.   
  151.  
  152. rd_buf = ws->buf; 
  153.  
  154. ws_frame_t * frame = ws->c_frame; 
  155.  
  156. char *payload_len_bytes = (char *)&frame->payload_len; 
  157.  
  158. for (i = 0; i 
  159.  
  160. *(payload_len_bytes + i) = rd_buf[PAYLOAD_LEN_BITS - 1 - i]; 
  161.  
  162.  
  163.   
  164.  
  165. ws__reset_buf(ws, PAYLOAD_LEN_BITS); 
  166.  
  167. ws->rd_state = WS_READ_PAYLOAD; 
  168.  
  169. #undef PAYLOAD_LEN_BITS 
  170.  
  171. break; 
  172.  
  173.  
  174. case WS_READ_PAYLOAD: { 
  175.  
  176. ws_frame_t * frame = ws->c_frame; 
  177.  
  178. uint64_t payload_len = frame->payload_len; 
  179.  
  180. ret = ws__make_up(ws, payload_len); 
  181.  
  182. if (ret != OK) { 
  183.  
  184. return ret; 
  185.  
  186.  
  187.   
  188.  
  189.   
  190.  
  191. rd_buf = ws->buf; 
  192.  
  193. frame->payload = malloc(payload_len); 
  194.  
  195. memcpy(frame->payload, rd_buf, payload_len); 
  196.  
  197.   
  198.  
  199. ws__reset_buf(ws, payload_len); 
  200.  
  201.   
  202.  
  203. if (frame->fin == 1) { 
  204.  
  205. // is control frame 
  206.  
  207. ws__dispatch_msg(ws, frame); 
  208.  
  209. ws__clean_frame(ws); 
  210.  
  211. else { 
  212.  
  213. ws__append_frame(ws); 
  214.  
  215.  
  216.   
  217.  
  218. ws->rd_state = WS_READ_IDLE; 
  219.  
  220.   
  221.  
  222. break; 
  223.  
  224.  
  225.  
  226.   
  227.  
  228. return ret; 
  229.  
  230.  

關閉連接

關閉連接分為兩種:服務端發(fā)起關閉和客戶端主動關閉。

服務端跟客戶端的處理基本一致,以服務端為例:

服務端發(fā)起關閉的時候,會客戶端發(fā)送一個關閉幀,客戶端在接收到幀的時候通過解析出幀的opcode來判斷是否是關閉幀,然后同樣向服務端再發(fā)送一個關閉幀作為回應。

  1. if (op_code == OP_CLOSE) { 
  2.  
  3. int status_code; 
  4.  
  5. char *reason; 
  6.  
  7. char *status_code_buf = (char *)&status_code; 
  8.  
  9. status_code_buf[0] = payload[1]; 
  10.  
  11. status_code_buf[1] = payload[0]; 
  12.  
  13. reason = payload + 2; 
  14.  
  15.   
  16.  
  17. if (ws->state != WS_STATE_CLOSED) { 
  18.  
  19. /** 
  20.  
  21. * should send response to remote server 
  22.  
  23. */ 
  24.  
  25.   
  26.  
  27. ws_send(ws, NULL, 0, OP_CLOSE | FLAG_FIN); 
  28.  
  29. ws->state = WS_STATE_CLOSED; 
  30.  
  31.  
  32.   
  33.  
  34. // close connection 
  35.  
  36. if (ws->close_cb) { 
  37.  
  38. ws->close_cb(ws, status_code, reason); 
  39.  
  40.  
  41.  

總結

對WebSocket的學習主要是對協(xié)議的理解,理解了協(xié)議,上面復雜的代碼自然而然就會明白~

后記

對于I/O操作的原理,推薦大家可以看看這個:epoll 或者 kqueue 的原理是什么?

https://www.zhihu.com/question/20122137/answer/14049112# 

責任編輯:龐桂玉 來源: iOS大全
相關推薦

2021-04-21 15:17:10

WebsocketWsnodejs

2024-01-11 08:53:58

2021-04-27 18:12:22

WebSocket持久化連接HTTP

2021-04-21 07:52:39

核心SignalR應用

2021-02-26 12:37:39

WebSocketOkHttp連接

2020-03-19 10:13:13

OkHttpWebSocket

2025-01-27 12:31:23

PythonLocustWebSocket

2021-03-25 08:29:33

SpringBootWebSocket即時消息

2023-08-14 08:01:12

websocket8g用戶

2021-11-16 10:45:35

WebSocketWebShellLinux

2024-09-11 08:35:54

2024-09-12 14:50:08

2022-06-28 08:37:07

分布式服務器WebSocket

2024-11-14 11:56:45

2021-02-05 07:28:11

SpringbootNettyWebsocke

2013-04-12 10:05:49

HTML5WebSocket

2023-11-17 09:35:58

2021-10-13 08:21:52

Java websocket Java 基礎

2023-09-06 07:17:57

2023-07-26 07:28:55

WebSocket服務器方案
點贊
收藏

51CTO技術棧公眾號

a在线观看免费| 在线免费观看视频| 91福利在线尤物| 91色porny在线视频| 国产99在线|中文| 韩国一级黄色录像| xxxx日韩| 欧美日韩国产一二三| 17c丨国产丨精品视频| 青青草免费在线| 色一区二区三区| 国产欧美视频一区二区| 91在线色戒在线| 国产99久久久| 欧美精品首页| 自拍偷拍亚洲一区| 国产精品亚洲无码| 一区二区三区视频播放| 久久久精品综合| 亚洲影视九九影院在线观看| 亚洲黄色激情视频| 欧美在线播放| 在线精品高清中文字幕| av鲁丝一区鲁丝二区鲁丝三区| 国产精品传媒麻豆hd| 精品国产福利视频| 欧美日韩激情四射| 久草资源在线| 久久99精品国产麻豆婷婷| 欧美国产在线视频| 欧美视频一区二区在线| 在线观看日韩av| 精品免费国产二区三区| 91成人在线观看喷潮教学| 午夜不卡视频| 99久久精品费精品国产| 日韩av在线网站| 精品中文视频在线| 欧美熟妇精品一区二区| av久久网站| 欧美性xxxx极品hd满灌| 成年人看的毛片| 成人免费网址| 久久国产福利国产秒拍| 欧美在线视频观看免费网站| 国产一级在线观看视频| 亚洲欧洲日韩| 久久精品国产精品亚洲| 国产午夜精品福利视频| 欧美r级在线| 欧美激情一区二区| 日韩在线电影一区| 黄色在线视频观看网站| 久久亚洲一区二区三区四区| 国产一区二区无遮挡| 欧美一级淫片免费视频魅影视频| 国产美女精品一区二区三区| 91沈先生在线观看| 99精品久久久久久中文字幕| 精品亚洲成a人| 91久久国产综合久久91精品网站| 国产又粗又长又黄| 国产中文一区| 日韩高清免费在线| 午夜性福利视频| 日韩免费一级| 精品国产三级电影在线观看| 性农村xxxxx小树林| 韩国女主播一区二区三区| 亚洲成人av片在线观看| 亚洲 欧美 日韩在线| 精品三级av在线导航| 精品视频在线播放| av手机在线播放| 99久久婷婷国产综合精品电影√| 久久精品国产一区二区电影| 男女羞羞免费视频| 国产欧美日韩一区二区三区在线| 日本不卡视频在线播放| 最近中文字幕免费观看| 国产原创一区二区三区| 国产一区二区精品免费| 精品成人一区二区三区免费视频| 亚洲国产精品精华液2区45| 日韩一区不卡| 黄色片在线播放| 日本一区二区三区在线观看| 一区二区三区免费看| 精品精品导航| 欧美在线观看18| 成年人看片网站| 九九精品在线| 精品国产免费一区二区三区四区| xfplay5566色资源网站| 精品国产一区二区三区噜噜噜 | 亚洲成人午夜影院| 亚洲国产一区二区精品视频| 超碰免费在线播放| 欧美日韩一区二区三区在线免费观看 | 成人免费大片黄在线播放| www.色视频| 国产亚洲欧美日韩在线一区| 永久免费看av| 日韩三区免费| 精品国产1区2区3区| 天天干天天操天天拍| 狠狠88综合久久久久综合网| 国产精品美女久久久久av超清| 成 人 免费 黄 色| 国产精品青草综合久久久久99| 欧美a级免费视频| 国产成+人+综合+亚洲欧美| 精品国产伦理网| 久久久久久视频| 欧美日韩国产在线观看网站| 九九热最新视频//这里只有精品 | 精品日产卡一卡二卡麻豆| 无码少妇精品一区二区免费动态| 亚洲婷婷免费| 91视频免费在线| 在线日本视频| 欧美性猛交xxxx乱大交极品| 久久无码专区国产精品s| 99久久九九| 国产精品日韩欧美| 欧美精品久久久久久久久久丰满| 亚洲自拍偷拍麻豆| 极品粉嫩美女露脸啪啪| 黑人操亚洲人| 人九九综合九九宗合| 五月婷婷在线播放| 亚洲一区二区五区| 国产免费一区二区视频| 国产精品伦一区二区| 亚洲欧美日韩另类| 久久国产黄色片| 91免费视频网| 成人av一级片| 午夜先锋成人动漫在线| 亚洲色图25p| 亚洲AV成人无码网站天堂久久| 亚洲欧美日韩一区在线观看| 国产日韩欧美一区二区三区四区| 精产国品自在线www| 欧美日韩中字一区| 欧美激情视频二区| 麻豆精品在线播放| 亚洲精品成人久久久998| 日韩精品一区二区三区av| 欧美精选午夜久久久乱码6080| 国产美女永久免费无遮挡| 午夜在线精品偷拍| 日本一区高清不卡| 粉嫩av一区二区三区四区五区 | 第四色日韩影片| 精品国产第一区二区三区观看体验| 欧美偷拍第一页| 从欧美一区二区三区| 97干在线视频| 国产精品调教视频| 欧洲s码亚洲m码精品一区| 欧美女优在线| 欧美日韩另类一区| 欧美人禽zoz0强交| 成人av中文字幕| 丰满人妻中伦妇伦精品app| 免费久久精品| 国产精自产拍久久久久久蜜| 黄色免费在线观看网站| 精品嫩草影院久久| 国产伦精品一区二区三区视频网站| 久久久午夜精品理论片中文字幕| 一区二区三区网址| 亚洲调教视频在线观看| 欧美日韩一区在线播放| 欧美在线一级| 97视频免费在线看| 永久免费av在线| 日韩你懂的在线播放| 精品国产一区二区三区四| 中文字幕高清一区| 娇妻高潮浓精白浆xxⅹ| 日韩电影在线一区二区| 99亚洲国产精品| 台湾佬综合网| 91在线免费视频| 欲香欲色天天天综合和网| 上原亚衣av一区二区三区| 国产黄色片网站| 91福利国产成人精品照片| 在线观看亚洲免费视频| 久久一本综合频道| 国产精品免费看久久久无码| 天堂成人娱乐在线视频免费播放网站| 国产精品自产拍在线观看中文| 福利在线免费视频| 久久精品国产亚洲| 国产精品天堂| 亚洲精品在线电影| 亚洲一级特黄毛片| 欧美视频在线免费看| 国产少妇在线观看| 欧美经典一区二区| 99re久久精品国产| 国产精品系列在线播放| 蜜桃免费在线视频| 先锋亚洲精品| 青春草国产视频| 天天色综合色| 日本高清一区| 校园春色另类视频| 官网99热精品| 精品久久国产一区| 国产美女扒开尿口久久久| 在线观看爽视频| 韩日精品中文字幕| 人妖欧美1区| 久久精品视频网站| 成人高清免费在线播放| 日韩av在线播放资源| www.国产黄色| 91精品国产91久久久久久一区二区| 中文字幕一区二区人妻视频| 午夜亚洲国产au精品一区二区| 欧美高清视频一区二区三区| 国产精品免费aⅴ片在线观看| 自拍偷拍亚洲天堂| 99re这里只有精品首页| 扒开伸进免费视频| 成人高清免费观看| 蜜臀视频在线观看| 国产东北露脸精品视频| 欧美体内she精高潮| 欧美日本一区二区高清播放视频| 亚洲精品影院| 久久国产成人精品| 亚洲一区影院| 日韩一区二区三区免费播放| 亚洲精品乱码久久久久久蜜桃91| 国产精品片aa在线观看| 免费日韩av电影| 欧美日韩爱爱| 日韩av一区二区三区在线观看| 一呦二呦三呦国产精品| 欧美一区二区三区精美影视| 精品在线99| 亚洲免费久久| 久久久久久久久99精品大| 亚洲最新免费视频| 中文字幕午夜精品一区二区三区| 法国空姐在线观看免费| 欧美国产精品| 极品美女扒开粉嫩小泬| 国产亚洲激情| 簧片在线免费看| 久久精品久久精品| 特种兵之深入敌后| 成人福利视频在线看| 91精品人妻一区二区| 国产亚洲综合色| 99国产精品无码| 亚洲靠逼com| 好吊操这里只有精品| 色狠狠桃花综合| 亚洲字幕av一区二区三区四区| 91精品国产综合久久久久久漫画 | 伊人久久亚洲综合| 日韩一区和二区| 日韩中文字幕观看| 亚洲视频在线观看网站| 麻豆最新免费在线视频| 欧美激情在线观看视频| 亚洲最大网站| 91免费国产网站| 色婷婷av一区二区三区丝袜美腿| 五月天色一区| 国产精品久av福利在线观看| 精品久久久久久一区二区里番| 国产成人调教视频在线观看| 在线观看亚洲视频啊啊啊啊| 欧美日韩国产高清| 黄色片视频在线播放| 黄色小说综合网站| 老熟妇精品一区二区三区| 国产精品毛片久久久久久| 久久久综合久久久| 欧美中文字幕一区二区三区| 国产999久久久| 亚洲色图综合网| 亚洲淫性视频| 国产精品video| 91国内精品白嫩初高生| 日韩精品一区二区三区四区五区| 在线国产一区| 任你操这里只有精品| 国产黑丝在线一区二区三区| 自拍偷拍中文字幕| 一区二区三区四区高清精品免费观看 | 四虎成人精品永久免费av九九| 精品欧美日韩| 亚洲91精品| 国产日韩成人内射视频| 久久aⅴ乱码一区二区三区| 天天做天天干天天操| 99re免费视频精品全部| 国产黄色片在线免费观看| 欧美亚洲一区二区三区四区| 日韩在线观看视频一区| 欧美剧在线观看| 99久久伊人| 蜜桃av噜噜一区二区三| 伊人久久久大香线蕉综合直播| 欧美日韩亚洲自拍| 久久新电视剧免费观看| 国产午夜福利片| 日韩欧美国产不卡| 蜜桃视频在线观看www社区 | 久久这里只有精品9| 亚洲精品福利免费在线观看| 伊人春色在线观看| 成人欧美一区二区三区黑人| 不卡中文字幕| 午夜肉伦伦影院| 91色porny在线视频| 日韩特黄一级片| 精品久久国产字幕高潮| 在线免费观看的av| 91精品啪在线观看麻豆免费 | 中文字幕九色91在线| 欧美舌奴丨vk视频| 欧美凹凸一区二区三区视频| 在线一区欧美| 免费看黄色aaaaaa 片| 精品久久久久久中文字幕一区奶水| 亚洲国产精品suv| 欧美精品一区二区免费| 日本精品在线播放| 免费cad大片在线观看| 国产成人亚洲综合a∨婷婷 | 少妇人妻大乳在线视频| 国产精久久久| 久久国产精品一区二区三区四区| 久久亚洲影视| 国产精品视频黄色| 久久久久久久精| 久草视频一区二区| 国产丝袜一区二区三区| 色综合桃花网| 欧美凹凸一区二区三区视频 | 国产午夜精品一区二区三区嫩草 | 色94色欧美sute亚洲线路一ni | 国产 福利 在线| 99re这里都是精品| 亚洲另类欧美日韩| 亚洲欧美制服中文字幕| 亚洲综合在线电影| 亚洲视频欧美在线| 国产麻豆精品95视频| 国产亚洲精品码| 亚洲国产精品成人一区二区| 黄视频免费在线看| 日韩亚洲视频| 国产激情一区二区三区| 日本熟妇乱子伦xxxx| 国产成人在线视频免费播放| 欧美黑人性猛交xxx| 精品久久久久久无| 中文字幕在线视频网站| 日韩精品国内| 激情综合色播激情啊| 国产亚洲精品码| 亚洲午夜色婷婷在线| 欧美另类tv| 九色综合婷婷综合| 日本欧美一区二区| 亚洲av鲁丝一区二区三区| 欧美精品一区二| 国产 日韩 欧美一区| 中国老女人av| wwwwxxxxx欧美| 亚洲天堂网在线观看视频| 欧美国产极速在线| 久久99久久人婷婷精品综合| 婷婷中文字幕在线观看| 亚瑟在线精品视频| 91精彩视频在线观看| 国产精品有限公司| 久久se精品一区精品二区| 国产精品第一页在线观看| 在线亚洲国产精品网| 成人看片黄a免费看视频| 午夜免费福利在线| 亚洲国产精品久久人人爱| 成人动漫在线播放| 精品久久久久久乱码天堂| 激情综合网天天干| 中文字幕视频网站| 欧美激情中文字幕乱码免费| 精品国产一区二区三区久久久樱花 | 色图在线观看|