国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

沉寂了一周,我開發了一個聊天室

開發 前端
今天,我們來從零開始開發一款聊天室。好,我們現在就開始。

[[381137]]

 前言

最近一周沒有發文章了,我在這里向大家說一聲抱歉。今天,我們來從零開始開發一款聊天室。好,我們現在就開始。

了解WebSocket

開發聊天室,我們需要用到WebSocket這個網絡通信協議,那么為什么會用到它呢?

我們首先來引用阮一峰大佬的一篇文章一段話:

  • 初次接觸 WebSocket 的人,都會問同樣的問題:我們已經有了 HTTP 協議,為什么還需要另一個協議?它能帶來什么好處?
  • 答案很簡單,因為 HTTP 協議有一個缺陷:通信只能由客戶端發起。
  • 舉例來說,我們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議做不到服務器主動向客戶端推送信息。
  • 這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用"輪詢":每隔一段時候,就發出一個詢問,了解服務器有沒有新的信息。最典型的場景就是聊天室。
  • 輪詢的效率低,非常浪費資源(因為必須不停連接,或者 HTTP 連接始終打開)。因此,工程師們一直在思考,有沒有更好的方法。WebSocket 就是這樣發明的。

我們來借用MDN網站上的官方介紹總結一下:

WebSockets 是一種先進的技術。它可以在用戶的瀏覽器和服務器之間打開交互式通信會話。使用此API,您可以向服務器發送消息并接收事件驅動的響應,而無需通過輪詢服務器的方式以獲得響應。

WebSocket 協議在2008年誕生,2011年成為國際標準。

WebSocket特點

服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種。

建立在 TCP 協議之上,服務器端的實現比較容易。

與 HTTP 協議有著良好的兼容性。默認端口也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器。

數據格式比較輕量,性能開銷小,通信高效。

可以發送文本,也可以發送二進制數據。

沒有同源限制,客戶端可以與任意服務器通信。

協議標識符是ws(如果加密,則為wss),即ws對應http,wss對應https。服務器網址就是 URL。即ws://www.xx.com或wss://www.xx.com

WebSocket客戶端常用API

WebSocket 對象提供了用于創建和管理 WebSocket連接,以及可以通過該連接發送和接收數據的 API。

使用WebSocket()構造函數來構造一個WebSocket 。

屬性

1.WebSocket.onopen

用于指定連接成功后的回調函數。

2.WebSocket.onmessage

用于指定當從服務器接受到信息時的回調函數。

3.WebSocket.onclose

用于指定連接關閉后的回調函數。

4.WebSocket.onerror

用于指定連接失敗后的回調函數。

方法

1.WebSocket.close()

關閉當前鏈接。

2.WebSocket.send(data)

客戶端發送數據到服務器,對要傳輸的數據進行排隊。

客戶端舉例

  1. // Create WebSocket connection
  2. const socket = new WebSocket('ws://localhost:8080'); // 這里的地址是服務器的websocket服務地址 
  3.  
  4. // Connection opened 
  5. socket.onopen = function(evt) {  
  6.   console.log("Connection open ...");  
  7.   ws.send("Hello WebSockets!"); 
  8. }; 
  9.  
  10. // Listen for messages 
  11. socket.onmessage = function(evt) { 
  12.   console.log( "Received Message: " + evt.data); 
  13.   socket.close(); 
  14. }; 
  15.  
  16. // Connection closed 
  17. socket.onclose = function(evt) { 
  18.   console.log("Connection closed."); 
  19. }; 

常用的WebSocket服務端

這里服務端我們使用Node.js,這里向大家介紹幾個常用的庫。

  1. ws
  2. socket.io
  3. nodejs-websocket

具體用法,大家可以上網瀏覽詳細文檔,這里就不一一介紹啦。不過在這篇文章中。我將會給大家使用ws與nodejs-websocket這兩個模塊來分別進行項目開發。

客戶端與服務端都介紹完啦!我們就趕快行動起來吧!

開發本地端(或局域網)聊天室(第一種)

我們將基于Vue.js@3.0開發聊天室,原因是擁抱新技術。怎么搭建vue腳手架,這里就不介紹了,想必大家也會。我們直接就上代碼。

客戶端

  1. <template> 
  2.   <div class="home"
  3.     <div class="count"
  4.       <p>在線人數:{{ count }}</p> 
  5.     </div> 
  6.     <div class="content"
  7.       <div class="chat-box" ref="chatBox"
  8.         <div 
  9.           v-for="(item, index) in chatArr" 
  10.           :key="index" 
  11.           class="chat-item" 
  12.         > 
  13.           <div v-if="item.name === name" class="chat-msg mine"
  14.             <p class="msg mineBg">{{ item.txt }}</p> 
  15.             <p class="user" :style="{ background: bg }"
  16.               {{ item.name.substring(item.name.length - 5, item.name.length) }} 
  17.             </p> 
  18.           </div> 
  19.           <div v-else class="chat-msg other"
  20.             <p class="user" :style="{ background: item.bg }"
  21.               {{ item.name.substring(item.name.length - 5, item.name.length) }} 
  22.             </p> 
  23.             <p class="msg otherBg">{{ item.txt }}</p> 
  24.           </div> 
  25.         </div> 
  26.       </div> 
  27.     </div> 
  28.     <div class="footer"
  29.       <textarea 
  30.         placeholder="說點什么..." 
  31.         v-model="textValue" 
  32.         autofocus 
  33.         ref="texta" 
  34.         @keyup.enter="send" 
  35.       ></textarea> 
  36.       <div class="send-box"
  37.         <p class="send active" @click="send">發送</p> 
  38.       </div> 
  39.     </div> 
  40.   </div> 
  41. </template> 
  42.  
  43. <script> 
  44. import { onMounted, onUnmounted, ref, reactive, nextTick } from "vue"
  45. export default { 
  46.   name"Home"
  47.   setup() { 
  48.     let socket = null
  49.     const path = "ws://localhost:3000/"; // 本地服務器地址 
  50.     const textValue = ref(""); 
  51.     const chatBox = ref(null); 
  52.     const texta = ref(null); 
  53.     const count = ref(0); 
  54.     const name = new Date().getTime().toString(); 
  55.     const bg = randomRgb(); 
  56.     const chatArr = reactive([]); 
  57.     function init() { 
  58.       if (typeof WebSocket === "undefined") { 
  59.         alert("您的瀏覽器不支持socket"); 
  60.       } else { 
  61.         socket = new WebSocket(path); 
  62.         socket.onopen = open
  63.         socket.onerror = error; 
  64.         socket.onclose = closed; 
  65.         socket.onmessage = getMessage; 
  66.         window.onbeforeunload = function(e) { 
  67.           e = e || window.event; 
  68.           if (e) { 
  69.             e.returnValue = "關閉提示"
  70.             socket.close(); 
  71.           } 
  72.           socket.close(); 
  73.           return "關閉提示"
  74.         }; 
  75.       } 
  76.     } 
  77.     function open() { 
  78.       alert("socket連接成功"); 
  79.     } 
  80.     function error() { 
  81.       alert("連接錯誤"); 
  82.     } 
  83.     function closed() { 
  84.       alert("socket關閉"); 
  85.     } 
  86.     async function getMessage(msg) { 
  87.       if (typeof JSON.parse(msg.data) === "number") { 
  88.         console.log(JSON.parse(msg.data)); 
  89.         count.value = msg.data; 
  90.       } else { 
  91.         const obj = JSON.parse(msg.data); 
  92.         chatArr.push(obj); 
  93.       } 
  94.       await nextTick(); 
  95.       chatBox.value.scrollTop = chatBox.value.scrollHeight; 
  96.     } 
  97.     function randomRgb() { 
  98.       let R = Math.floor(Math.random() * 130 + 110); 
  99.       let G = Math.floor(Math.random() * 130 + 110); 
  100.       let B = Math.floor(Math.random() * 130 + 110); 
  101.       return "rgb(" + R + "," + G + "," + B + ")"
  102.     } 
  103.     function send() { 
  104.       if (textValue.value.trim().length > 0) { 
  105.         const obj = { 
  106.           namename
  107.           txt: textValue.value, 
  108.           bg: bg, 
  109.         }; 
  110.         socket.send(JSON.stringify(obj)); 
  111.         textValue.value = ""
  112.         texta.value.focus(); 
  113.       } 
  114.     } 
  115.     function close() { 
  116.       alert("socket已經關閉"); 
  117.     } 
  118.     onMounted(() => { 
  119.       init(); 
  120.     }); 
  121.     onUnmounted(() => { 
  122.       socket.onclose = close
  123.     }); 
  124.     return { 
  125.       send, 
  126.       textValue, 
  127.       chatArr, 
  128.       name
  129.       bg, 
  130.       chatBox, 
  131.       texta, 
  132.       randomRgb, 
  133.       count
  134.     }; 
  135.   }, 
  136. }; 
  137. </script> 

至于樣式文件,這里我也貼出來。

  1. html,body{ 
  2.   background-color: #e8e8e8; 
  3.   user-select: none; 
  4. ::-webkit-scrollbar { 
  5.   width: 8px; 
  6.   height: 8px; 
  7.   display: none; 
  8. ::-webkit-scrollbar-thumb { 
  9.   background-color: #D1D1D1; 
  10.   border-radius: 3px; 
  11.   -webkit-border-radius: 3px; 
  12.   border-left: 2px solid transparent; 
  13.   border-top: 2px solid transparent; 
  14. *{ 
  15.   margin: 0; 
  16.   padding: 0; 
  17. .mine { 
  18.   justify-content: flex-end
  19. .other { 
  20.   justify-content: flex-start; 
  21. .mineBg { 
  22.   background: #98e165; 
  23. .otherBg { 
  24.   background: #fff; 
  25. .home { 
  26.   position: fixed; 
  27.   top: 0; 
  28.   left: 50%; 
  29.   transform: translateX(-50%); 
  30.   width: 100%; 
  31.   height: 100%; 
  32.   min-width: 360px; 
  33.   min-height: 430px; 
  34.   box-shadow: 0 0 24px 0 rgb(19 70 80 / 25%); 
  35. .count
  36.   height: 5%; 
  37.   display: flex; 
  38.   justify-content: center; 
  39.   align-items: center; 
  40.   background: #EEEAE8; 
  41.   font-size: 16px; 
  42. .content { 
  43.   width: 100%; 
  44.   height: 80%; 
  45.   background-color: #f4f4f4; 
  46.   overflow: hidden; 
  47. .footer { 
  48.   position: fixed; 
  49.   bottom: 0; 
  50.   width: 100%; 
  51.   height: 15%; 
  52.   background-color: #fff; 
  53. .footer textarea { 
  54.   width: 100%; 
  55.   height: 50%; 
  56.   background: #fff; 
  57.   border: 0; 
  58.   box-sizing: border-box; 
  59.   resize: none; 
  60.   outline: none; 
  61.   padding: 10px; 
  62.   font-size: 16px; 
  63. .send-box { 
  64.   display: flex; 
  65.   height: 40%; 
  66.   justify-content: flex-end
  67.   align-items: center; 
  68. .send { 
  69.   margin-right: 20px; 
  70.   cursor: pointer; 
  71.   border-radius: 3px; 
  72.   background: #f5f5f5; 
  73.   z-index: 21; 
  74.   font-size: 16px; 
  75.   padding: 8px 20px; 
  76. .send:hover { 
  77.   filter: brightness(110%); 
  78. .active { 
  79.   background: #98e165; 
  80.   color: #fff; 
  81. .chat-box { 
  82.   height: 100%; 
  83.   padding:0 20px; 
  84.   overflow-y: auto; 
  85. .chat-msg { 
  86.   display: flex; 
  87.   align-items: center; 
  88. .user { 
  89.   font-weight: bold; 
  90.   color: #fff; 
  91.   position: relative
  92.   word-wrap: break-word; 
  93.   box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 
  94.   width: 60px; 
  95.   height: 60px; 
  96.   line-height: 60px; 
  97.   border-radius:8px ; 
  98.   text-align: center; 
  99. .msg { 
  100.   margin: 0 5px; 
  101.   max-width: 74%; 
  102.   white-space: normal; 
  103.   word-break: break-all
  104.   color: #333; 
  105.   border-radius: 8px; 
  106.   padding: 10px; 
  107.   text-align: justify; 
  108.   font-size: 16px; 
  109.   box-shadow: 0px 0px 10px #f4f4f4; 
  110. .chat-item { 
  111.   margin: 20px 0; 
  112.   animation: up-down 1s both; 
  113. @keyframes up-down { 
  114.   0% { 
  115.     opacity: 0; 
  116.     transform: translate3d(0, 20px, 0); 
  117.   } 
  118.  
  119.   100% { 
  120.     opacity: 1; 
  121.     transform: none; 
  122.   } 

服務端

這里使用的是Node.js。

nodejs-websocket:websocket服務器和客戶端的nodejs模塊。

  1. const ws = require("nodejs-websocket"); 
  2. const server = ws.createServer((conn) => { 
  3.   conn.on("text", (str) => { 
  4.     broadcast(str); 
  5.   }); 
  6.   conn.on("error", (err) => { 
  7.     console.log(err); 
  8.   }); 
  9. }); 
  10. server.listen(3000, function () { 
  11.   console.log("open"); 
  12. }); 
  13. // 群發消息 
  14. function broadcast(data) { 
  15.   server.connections.forEach((conn) => { 
  16.     conn.sendText(data); 
  17.   }); 

項目一覽


在線人數為零,這不是bug,是因為當時在本地端沒有做,只是放上了這個版塊。不過,在云服務端我已經放上了這個功能。那么,我們來看一下吧。

開發云端聊天室(第二種)

客戶端‍

  1. <template> 
  2.   <div class="home"
  3.     <div class="count"
  4.       <p>在線人數:{{ count }}</p> 
  5.     </div> 
  6.     <div class="content"
  7.       <div class="chat-box" ref="chatBox"
  8.         <div 
  9.           v-for="(item, index) in chatArr" 
  10.           :key="index" 
  11.           class="chat-item" 
  12.         > 
  13.           <div v-if="item.name === name" class="chat-msg mine"
  14.             <p class="msg mineBg">{{ item.txt }}</p> 
  15.             <p class="user" :style="{ background: bg }"
  16.               {{ item.name.substring(item.name.length - 5, item.name.length) }} 
  17.             </p> 
  18.           </div> 
  19.           <div v-else class="chat-msg other"
  20.             <p class="user" :style="{ background: item.bg }"
  21.               {{ item.name.substring(item.name.length - 5, item.name.length) }} 
  22.             </p> 
  23.             <p class="msg otherBg">{{ item.txt }}</p> 
  24.           </div> 
  25.         </div> 
  26.       </div> 
  27.     </div> 
  28.     <div class="footer"
  29.       <textarea 
  30.         placeholder="說點什么..." 
  31.         v-model="textValue" 
  32.         autofocus 
  33.         ref="texta" 
  34.         @keyup.enter="send" 
  35.       ></textarea> 
  36.       <div class="send-box"
  37.         <p class="send active" @click="send">發送</p> 
  38.       </div> 
  39.     </div> 
  40.   </div> 
  41. </template> 
  42.  
  43. <script> 
  44. import { onMounted, onUnmounted, ref, reactive, nextTick } from "vue"
  45. export default { 
  46.   name"Home"
  47.   setup() { 
  48.     let socket = null
  49.     const path = "wss:/xxx.com/wsline/"; // 這個網址只是測試網址,這里只是說明云服務地址 
  50.     const textValue = ref(""); 
  51.     const chatBox = ref(null); 
  52.     const texta = ref(null); 
  53.     const count = ref(0); 
  54.     const name = new Date().getTime().toString(); 
  55.     const bg = randomRgb(); 
  56.     const chatArr = reactive([]); 
  57.     function init() { 
  58.       if (typeof WebSocket === "undefined") { 
  59.         alert("您的瀏覽器不支持socket"); 
  60.       } else { 
  61.         socket = new WebSocket(path); 
  62.         socket.onopen = open
  63.         socket.onerror = error; 
  64.         socket.onclose = closed; 
  65.         socket.onmessage = getMessage; 
  66.         window.onbeforeunload = function(e) { 
  67.           e = e || window.event; 
  68.           if (e) { 
  69.             e.returnValue = "關閉提示"
  70.             socket.close(); 
  71.           } 
  72.           socket.close(); 
  73.           return "關閉提示"
  74.         }; 
  75.       } 
  76.     } 
  77.     function open() { 
  78.       alert("socket連接成功"); 
  79.     } 
  80.     function error() { 
  81.       alert("連接錯誤"); 
  82.     } 
  83.     function closed() { 
  84.       alert("socket關閉"); 
  85.     } 
  86.     async function getMessage(msg) { 
  87.       if (typeof JSON.parse(msg.data) === "number") { 
  88.         console.log(JSON.parse(msg.data)); 
  89.         count.value = msg.data; 
  90.       } else { 
  91.         const obj = JSON.parse(msg.data); 
  92.         chatArr.push(obj); 
  93.       } 
  94.       await nextTick(); 
  95.       chatBox.value.scrollTop = chatBox.value.scrollHeight; 
  96.     } 
  97.     function randomRgb() { 
  98.       let R = Math.floor(Math.random() * 130 + 110); 
  99.       let G = Math.floor(Math.random() * 130 + 110); 
  100.       let B = Math.floor(Math.random() * 130 + 110); 
  101.       return "rgb(" + R + "," + G + "," + B + ")"
  102.     } 
  103.     function send() { 
  104.       if (textValue.value.trim().length > 0) { 
  105.         const obj = { 
  106.           namename
  107.           txt: textValue.value, 
  108.           bg: bg, 
  109.         }; 
  110.         socket.send(JSON.stringify(obj)); 
  111.         textValue.value = ""
  112.         texta.value.focus(); 
  113.       } 
  114.     } 
  115.     function close() { 
  116.       alert("socket已經關閉"); 
  117.     } 
  118.     onMounted(() => { 
  119.       init(); 
  120.     }); 
  121.     onUnmounted(() => { 
  122.       socket.onclose = close
  123.     }); 
  124.     return { 
  125.       send, 
  126.       textValue, 
  127.       chatArr, 
  128.       name
  129.       bg, 
  130.       chatBox, 
  131.       texta, 
  132.       randomRgb, 
  133.       count
  134.     }; 
  135.   }, 
  136. }; 
  137. </script> 

樣式文件同本地端樣式,可以查看上方的代碼。

服務端

這里我使用了ws模塊,并且我也搭建了https服務器,并使用了更為安全的wss協議。接下來,我們來看下是怎么操作的。

  1. const fs = require("fs"); 
  2. const httpServ = require("https"); 
  3. const WebSocketServer = require("ws").Server; // 引用Server類 
  4.  
  5. const cfg = { 
  6.   port: 3456, 
  7.   ssl_key: "../../https/xxx.key", // 配置https所需的文件2 
  8.   ssl_cert: "../../https/xxx.crt", // 配置https所需的文件1 
  9. }; 
  10.  
  11. // 創建request請求監聽器 
  12. const processRequest = (req, res) => { 
  13.   res.writeHead(200); 
  14.   res.end("Websocket linked successfully"); 
  15. }; 
  16.  
  17. const app = httpServ 
  18.   .createServer( 
  19.     { 
  20.       // 向server傳遞key和cert參數 
  21.       key: fs.readFileSync(cfg.ssl_key), 
  22.       cert: fs.readFileSync(cfg.ssl_cert), 
  23.     }, 
  24.     processRequest 
  25.   ) 
  26.   .listen(cfg.port); 
  27.  
  28. // 實例化WebSocket服務器 
  29. const wss = new WebSocketServer({ 
  30.   server: app, 
  31. }); 
  32. // 群發 
  33. wss.broadcast = function broadcast(data) { 
  34.     wss.clients.forEach(function each(client) { 
  35.       client.send(data); 
  36.     }); 
  37. }; 
  38. // 如果有WebSocket請求接入,wss對象可以響應connection事件來處理 
  39. wss.on("connection", (wsConnect) => { 
  40.   console.log("Server monitoring"); 
  41.   wss.broadcast(wss._server._connections); 
  42.   wsConnect.on("message", (message) => { 
  43.     wss.broadcast(message); 
  44.   }); 
  45.   wsConnect.on("close"function close() { 
  46.     console.log("disconnected"); 
  47.     wss.broadcast(wss._server._connections); 
  48.   }); 
  49. }); 

我們在云服務上啟動命令。

啟動成功!

 

這里還沒有結束,因為你使用的是ip地址端口,必須轉發到域名上。所以我使用的nginx進行轉發,配置如下參數。

  1. location /wsline/ { 
  2.      proxy_pass https://xxx:3456/; 
  3.      proxy_http_version 1.1; 
  4.      proxy_set_header Upgrade $http_upgrade; 
  5.      proxy_set_header Connection "Upgrade"
  6.      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  7.      proxy_set_header Host $http_host; 
  8.      proxy_set_header X-Real-IP $remote_addr; 
  9.      proxy_set_header X-Forwarded-Proto https; 
  10.      proxy_redirect off

那么,重啟云端服務器,看下效果。

項目一覽

 

那么,到這里一款云端聊天室就這么做成了,可以實時顯示在線人數,這樣你就可以知道有多少人在這里跟你聊天。

結語

謝謝閱讀,希望我沒有浪費你的時間。看完文章了,那么趕快行動起來吧,開發一款屬于自己的聊天室。

 

責任編輯:姜華 來源: 前端歷劫之路
相關推薦

2022-11-14 08:01:48

2024-01-18 11:15:46

Pythonsocket聊天室

2023-02-13 00:18:22

前端庫框架集合

2022-11-10 09:28:40

框架開發

2011-12-15 11:11:51

JavaNIO

2023-02-10 08:16:48

WebSocket簡易聊天室

2020-02-16 11:13:39

遠程辦公工具技術

2023-07-10 09:53:59

console開發插件

2021-04-26 07:31:22

SpringMVCweb框架

2022-07-26 14:53:10

WebSocket網絡通信協議

2016-07-25 18:09:29

2013-12-05 09:17:29

程序員Bug

2021-12-29 19:20:41

數據GitHub服務器

2020-11-04 07:56:19

工具Linux 翻譯

2021-12-09 16:48:25

鴻蒙HarmonyOS應用

2015-04-13 00:24:17

2015-07-06 10:42:18

PHP聊天室應用

2021-11-16 09:38:10

鴻蒙HarmonyOS應用

2021-10-14 18:46:29

Websocket瀏覽器API

2020-09-27 14:13:50

Spring BootJava框架
點贊
收藏

51CTO技術棧公眾號

亚洲国产一二三精品无码| 涩涩在线视频| 久久99精品久久久久久久久久久久| 91精品国产乱码久久久久久蜜臀| 另类激情视频| 欧美一区二区三区视频免费播放 | 亚洲资源在线| 亚洲精品成a人在线观看| 成人亚洲性情网站www在线观看| 中文字幕精品一区二区精品绿巨人| 日韩不卡视频一区二区| 看电视剧不卡顿的网站| 蜜桃导航-精品导航| 天天色综合色| 91久久精品美女高潮| 国产精品一在线观看| 欧亚精品中文字幕| 亚洲区小说区| 国产99视频精品免视看7| 丝袜美腿综合| 国产精品扒开腿做爽爽爽的视频| 小嫩嫩12欧美| 国产精品美女在线| 99热国内精品永久免费观看| 成人美女免费网站视频| 小处雏高清一区二区三区| 91情侣偷在线精品国产| 天天射成人网| 亚洲最大福利视频网| 欧美在线三级| 国产欧美一区二区三区另类精品 | 国产超碰在线观看| 亚洲综合一二三区| 中文字幕网站视频在线| 色哟哟国产精品免费观看| 黄色av免费在线观看| 欧美一区二区三区小说| xxxx另类黑人| 日韩中文在线视频| 中文一区二区三区四区| 日本电影亚洲天堂| 99精品视频在线观看播放| 风间由美久久久| 日韩精品电影一区亚洲| 免费超爽大片黄| 中文字幕在线不卡视频| 在线免费av观看| 欧美高清www午色夜在线视频| 成人免费影院| 91黑丝在线观看| 欧美一区二区三区久久精品| 亚洲精品视频一区二区三区| 成人av第一页| 最新理论片影院| 日韩一区二区视频在线观看| 精品成人免费一区二区在线播放| 欧美亚洲午夜视频在线观看| 很黄很黄激情成人| 欧美日韩午夜爽爽| 一区二区日韩电影| 免费a在线看| 韩国视频一区二区| 怡红院av亚洲一区二区三区h| 欧美gay男男猛男无套| 日本亚洲导航| 亚洲国产成人私人影院tom| 欧美1234区| 日本欧美精品久久久| 国产一区二区成人久久免费影院 | 日韩久久电影| 91影视免费在线观看| 亚洲精品欧美激情| 日韩在线观看不卡| 熟妇熟女乱妇乱女网站| 日韩中文字幕av| 国产精品一线| 免费无码国产v片在线观看| 亚洲欧美激情视频| 99久久精品99国产精品| 888av在线视频| 欧美成熟毛茸茸复古| 国产日韩欧美一区二区三区乱码| 日本中文字幕在线2020| 国产精品18毛片一区二区| 国产欧美日韩在线| 日本精品不卡| 日本午夜精品理论片a级appf发布| 久久xxxx| 黄视频网站在线观看| 麻豆精品传媒视频| 在线观看日韩精品| 亚洲精品二区三区| 久久夜夜操妹子| 不卡的av中文字幕| 3d成人动漫网站| 精品在线播放免费| 污污的网站在线免费观看| 国产一区二区不卡老阿姨| 国产精品久久久久白浆| 亚洲欧洲国产精品| 欧美午夜久久| 超碰超碰在线观看| 中文字幕久久亚洲| 爽爽淫人综合网网站| 在线观看av中文| 97精品伊人久久久大香线蕉| 国产传媒久久文化传媒| 国产在线高清视频| 91在线直播亚洲| 亚洲欧美偷拍卡通变态| 影视一区二区三区| 欧美久久在线| 色综合色综合色综合色综合色综合 | 在线免费观看a视频| 成人黄色午夜影院| 中文字幕av一区二区三区高| 日韩免费va| 亚洲一区二区免费视频软件合集 | 伊人久久大香线蕉| **三级三级97片毛片| 国产亚洲成精品久久| 日本aⅴ亚洲精品中文乱码| 青青青草网站免费视频在线观看| 欧美中文字幕在线| 国产精品久久久久久久久免费丝袜| 日韩电影免费观| 亚洲免费av网| 亚洲国产日韩精品在线| 老牛嫩草一区二区三区日本| 成年在线电影| 国产传媒欧美日韩| 在线免费观看一区| 尹人成人综合网| 日韩伦理在线观看| 久久久久久久久久久久久久久久av| 欧美性生活大片免费观看网址| 日韩国产综合| 传媒av在线| 亚洲bt天天射| 欧美日韩一区成人| 亚洲在线电影| 蜜桃视频www网站在线观看| 宅男av一区二区三区| 亚洲人线精品午夜| 91麻豆免费在线观看| 久久久久观看| 最猛黑人系列在线播放| 成人片在线免费看| 欧美一级黄色大片| 国产一区二区导航在线播放| 日韩天堂在线| 国产理论在线播放| 国产精品在线看| 欧美精品国产精品| 激情亚洲综合在线| 欧美三级一区| 情趣网站视频在线观看| 精品无人乱码一区二区三区的优势| 日韩欧美成人一区二区| 白白色 亚洲乱淫| 亚洲欧美日本伦理| 国产无套粉嫩白浆在线2022年| 国产精品手机在线| 国产丝袜精品视频| 久久人人爽爽爽人久久久| 国内精品久久久久久久久电影网 | 丁香六月综合激情| 中文无码日韩欧| 性网站在线免费观看| 国产在线资源一区| 日韩精品视频在线观看网址| 99re在线精品| 欧美在线电影| av免费在线网站| 黄色一级片黄色| 国产精品吹潮在线观看| 欧美精选午夜久久久乱码6080| 久久成人麻豆午夜电影| 成人爽a毛片免费啪啪红桃视频| 污网站免费在线观看| 影音先锋欧美在线| 欧美在线激情网| 日韩欧美国产一区二区三区| 久久精品一区二区三区不卡牛牛| 欧美激情视频一区二区三区免费| 欧美黄色三级| 飘雪影院手机免费高清版在线观看| 在线不卡日本| 日韩女优在线播放| 亚洲国产精品大全| 亚洲在线成人精品| 久久成人免费电影| 欧洲激情综合| 欧美在线va视频| 最近中文视频在线| 精品无码一区二区三区在线| 91日韩在线播放| 欧美精品做受xxx性少妇| 欧美剧在线免费观看网站| 国产精品蜜臀在线观看|