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

使用Node.js+Socket.IO搭建WebSocket實時應用

移動開發 Android
Web領域的實時推送技術,也被稱作Realtime技術。這種技術要達到的目的是讓用戶不需要刷新瀏覽器就可以獲得實時更新。它有著廣泛的應用場景,比如在線聊天室、在線客服系統、評論系統、WebIM等。本文就讓我們來看看如何搭建一個Web實時應用。

Web領域的實時推送技術,也被稱作Realtime技術。這種技術要達到的目的是讓用戶不需要刷新瀏覽器就可以獲得實時更新。它有著廣泛的應用場景,比如在線聊天室、在線客服系統、評論系統、WebIM等。

WebSocket簡介

談到Web實時推送,就不得不說WebSocket。在WebSocket出現之前,很多網站為了實現實時推送技術,通常采用的方案是輪詢 (Polling)和Comet技術,Comet又可細分為兩種實現方式,一種是長輪詢機制,一種稱為流技術,這兩種方式實際上是對輪詢技術的改進,這些 方案帶來很明顯的缺點,需要由瀏覽器對服務器發出HTTP request,大量消耗服務器帶寬和資源。面對這種狀況,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬并實現真正意義上的實 時推送。

WebSocket協議本質上是一個基于TCP的協議,它由通信協議和編程API組成,WebSocket能夠在瀏覽器和服務器之間建立雙向連接, 以基于事件的方式,賦予瀏覽器實時通信能力。既然是雙向通信,就意味著服務器端和客戶端可以同時發送并響應請求,而不再像HTTP的請求和響應。

為了建立一個WebSocket連接,客戶端瀏覽器首先要向服務器發起一個HTTP請求,這個請求和通常的HTTP請求不同,包含了一些附加頭信 息,其中附加頭信息”Upgrade: WebSocket”表明這是一個申請協議升級的HTTP請求,服務器端解析這些附加的頭信息然后產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket連接就建立起來了,雙方就可以通過這個連接通道自由的傳遞信息,并且這個連接會持續存在直到客戶端或者服務器端的某一方主動的關閉連 接。

一個典型WebSocket客戶端請求頭:

前面講到WebSocket是HTML5中新增的一種通信協議,這意味著一部分老版本瀏覽器(主要是IE10以下版本)并不具備這個功能, 通過百度統計的公開數據顯示,IE8 目前仍以33%的市場份額占據榜首,好在chrome瀏覽器市場份額逐年上升,現在以超過26%的市場份額位居第二,同時微軟前不久宣布停止對IE6的技 術支持并提示用戶更新到新版本瀏覽器,這個曾經讓無數前端工程師為之頭疼的瀏覽器有望退出歷史舞臺,再加上幾乎所有的智能手機瀏覽器都支持HTML5,所 以使得WebSocket的實戰意義大增,但是無論如何,我們實際的項目中,仍然要考慮低版本瀏覽器的兼容方案:在支持WebSocket的瀏覽器中采用 新技術,而在不支持WebSocket的瀏覽器里啟用Comet來接收發送消息。

WebSocket實戰

本文將以多人在線聊天應用作為實例場景,我們先來確定這個聊天應用的基本需求。

需求分析

1、兼容不支持WebSocket的低版本瀏覽器。
2、允許客戶端有相同的用戶名。
3、進入聊天室后可以看到當前在線的用戶和在線人數。
4、用戶上線或退出,所有在線的客戶端應該實時更新。
5、用戶發送消息,所有客戶端實時收取。

在實際的開發過程中,為了使用WebSocket接口構建Web應用,我們首先需要構建一個實現了 WebSocket規范的服務端,服務端的實現不受平臺和開發語言的限制,只需要遵從WebSocket規范即可,目前已經出現了一些比較成熟的 WebSocket服務端實現,比如本文使用的Node.js+Socket.IO。為什么選用這個方案呢?先來簡單介紹下他們兩。

Node.js

Node.js采用C++語言編寫而成,它不是Javascript應用,而是一個Javascript的運行環境,據Node.js創始人 Ryan Dahl回憶,他最初希望采用Ruby來寫Node.js,但是后來發現Ruby虛擬機的性能不能滿足他的要求,后來他嘗試采用V8引擎,所以選擇了 C++語言。

Node.js支持的系統包括*nux、Windows,這意味著程序員可以編寫系統級或者服務器端的Javascript代碼,交給 Node.js來解釋執行。Node.js的Web開發框架Express,可以幫助程序員快速建立web站點,從2009年誕生至今,Node.js的 成長的速度有目共睹,其發展前景獲得了技術社區的充分肯定。

Socket.IO

Socket.IO是一個開源的WebSocket庫,它通過Node.js實現WebSocket服務端,同時也提供客戶端JS庫。Socket.IO支持以事件為基礎的實時雙向通訊,它可以工作在任何平臺、瀏覽器或移動設備。

Socket.IO支持4種協議:WebSocket、htmlfile、xhr-polling、jsonp-polling,它會自動根據瀏覽 器選擇適合的通訊方式,從而讓開發者可以聚焦到功能的實現而不是平臺的兼容性,同時Socket.IO具有不錯的穩定性和性能。

編碼實現

本文一開始的的插圖就是效果演示圖:可以點擊這里查看在線演示,整個開發過程非常簡單,下面簡單記錄了開發步驟:

安裝Node.js

根據自己的操作系統,去Node.js官網下載安裝即可。如果成功安裝。在命令行輸入node -vnpm -v應該能看到相應的版本號。

node -v  
v0.10.26  
npm -v  
1.4.6  

搭建WebSocket服務端

這個環節我們盡可能的考慮真實生產環境,把WebSocket后端服務搭建成一個線上可以用域名訪問的服務,如果你是在本地開發環境,可以換成本地ip地址,或者使用一個虛擬域名指向本地ip。

先進入到你的工作目錄,比如 /workspace/wwwroot/plhwin/realtime.plhwin.com,新建一個名為 package.json的文件,內容如下:

  1.   "name""realtime-server"
  2.   "version""0.0.1"
  3.   "description""my first realtime server"
  4.   "dependencies": {} 

接下來使用npm命令安裝expresssocket.io

npm install --save express
npm install --save socket.io

安裝成功后,應該可以看到工作目錄下生成了一個名為node_modules的文件夾,里面分別是expresssocket.io,接下來可以開始編寫服務端的代碼了,新建一個文件:index.js

  1. var app = require('express')(); 
  2. var http = require('http').Server(app); 
  3. var io = require('socket.io')(http); 
  4.  
  5. app.get('/'function(req, res){ 
  6.     res.send('<h1>Welcome Realtime Server</h1>'); 
  7. }); 
  8.  
  9. http.listen(3000, function(){ 
  10.     console.log('listening on *:3000'); 
  11. }); 

命令行運行node index.js,如果一切順利,你應該會看到返回的listening on *:3000字樣,這說明服務已經成功搭建了。此時瀏覽器中打開http://localhost:3000應該可以看到正常的歡迎頁面。

如果你想要讓服務運行在線上服務器,并且可以通過域名訪問的話,可以使用Nginx做代理,在nginx.conf中添加如下配置,然后將域名(比如:realtime.plhwin.com)解析到服務器IP即可。

  1. server 
  2.   listen       80; 
  3.   server_name  realtime.plhwin.com; 
  4.   location / { 
  5.     proxy_pass http://127.0.0.1:3000; 
  6.   } 

完成以上步驟,http://realtime.plhwin.com:3000的后端服務就正常搭建了。

服務端代碼實現

前面講到的index.js運行在服務端,之前的代碼只是一個簡單的WebServer歡迎內容,讓我們把WebSocket服務端完整的實現代碼加入進去,整個服務端就可以處理客戶端的請求了。完整的index.js代碼如下:

  1. var app = require('express')(); 
  2. var http = require('http').Server(app); 
  3. var io = require('socket.io')(http); 
  4.  
  5. app.get('/'function(req, res){ 
  6.     res.send('<h1>Welcome Realtime Server</h1>'); 
  7. }); 
  8.  
  9. //在線用戶 
  10. var onlineUsers = {}; 
  11. //當前在線人數 
  12. var onlineCount = 0; 
  13.  
  14. io.on('connection'function(socket){ 
  15.     console.log('a user connected'); 
  16.      
  17.     //監聽新用戶加入 
  18.     socket.on('login'function(obj){ 
  19.         //將新加入用戶的唯一標識當作socket的名稱,后面退出的時候會用到 
  20.         socket.name = obj.userid; 
  21.          
  22.         //檢查在線列表,如果不在里面就加入 
  23.         if(!onlineUsers.hasOwnProperty(obj.userid)) { 
  24.             onlineUsers[obj.userid] = obj.username; 
  25.             //在線人數+1 
  26.             onlineCount++; 
  27.         } 
  28.          
  29.         //向所有客戶端廣播用戶加入 
  30.         io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj}); 
  31.         console.log(obj.username+'加入了聊天室'); 
  32.     }); 
  33.      
  34.     //監聽用戶退出 
  35.     socket.on('disconnect'function(){ 
  36.         //將退出的用戶從在線列表中刪除 
  37.         if(onlineUsers.hasOwnProperty(socket.name)) { 
  38.             //退出用戶的信息 
  39.             var obj = {userid:socket.name, username:onlineUsers[socket.name]}; 
  40.              
  41.             //刪除 
  42.             delete onlineUsers[socket.name]; 
  43.             //在線人數-1 
  44.             onlineCount--; 
  45.              
  46.             //向所有客戶端廣播用戶退出 
  47.             io.emit('logout', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj}); 
  48.             console.log(obj.username+'退出了聊天室'); 
  49.         } 
  50.     }); 
  51.      
  52.     //監聽用戶發布聊天內容 
  53.     socket.on('message'function(obj){ 
  54.         //向所有客戶端廣播發布的消息 
  55.         io.emit('message', obj); 
  56.         console.log(obj.username+'說:'+obj.content); 
  57.     }); 
  58.    
  59. }); 
  60.  
  61. http.listen(3000, function(){ 
  62.     console.log('listening on *:3000'); 
  63. }); 

客戶端代碼實現

進入客戶端工作目錄/workspace/wwwroot/plhwin/demo.plhwin.com/chat,新建一個index.html:

  1. <!DOCTYPE html> 
  2. <html> 
  3.     <head> 
  4.         <meta charset="utf-8"> 
  5.         <meta name="format-detection" content="telephone=no"/> 
  6.         <meta name="format-detection" content="email=no"/> 
  7. <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" name="viewport"> 
  8.         <title>多人聊天室</title> 
  9.         <link rel="stylesheet" type="text/css" href="./style.css" /> 
  10.         <!--[if lt IE 8]><script src="./json3.min.js"></script><![endif]--> 
  11.         <script src="http://realtime.plhwin.com:3000/socket.io/socket.io.js"></script> 
  12.     </head> 
  13.     <body> 
  14.         <div id="loginbox"> 
  15.             <div style="width:260px;margin:200px auto;"> 
  16.                 請先輸入你在聊天室的昵稱 
  17.                 <br/> 
  18.                 <br/> 
  19.                 <input type="text" style="width:180px;" placeholder="請輸入用戶名" id="username" name="username" /> 
  20.                 <input type="button" style="width:50px;" value="提交" onclick="CHAT.usernameSubmit();"/> 
  21.             </div> 
  22.         </div> 
  23.         <div id="chatbox" style="display:none;"> 
  24.             <div style="background:#3d3d3d;height: 28px; width: 100%;font-size:12px;"> 
  25.                 <div style="line-height: 28px;color:#fff;"> 
  26.                     <span style="text-align:left;margin-left:10px;">Websocket多人聊天室</span> 
  27.                     <span style="float:right; margin-right:10px;"><span id="showusername"></span> |  
  28.                     <a href="javascript:;" onclick="CHAT.logout()" style="color:#fff;">退出</a></span> 
  29.                 </div> 
  30.             </div> 
  31.             <div id="doc"> 
  32.                 <div id="chat"> 
  33.                     <div id="message" class="message"> 
  34. <div id="onlinecount" style="background:#EFEFF4; font-size:12px; margin-top:10px; margin-left:10px; color:#666;"> 
  35. </div> 
  36.                     </div> 
  37.                     <div class="input-box"> 
  38.                         <div class="input"> 
  39. <input type="text" maxlength="140" placeholder="請輸入聊天內容,按Ctrl提交" id="content" name="content"> 
  40.                         </div> 
  41.                         <div class="action"> 
  42.                             <button type="button" id="mjr_send" onclick="CHAT.submit();">提交</button> 
  43.                         </div> 
  44.                     </div> 
  45.                 </div> 
  46.             </div> 
  47.         </div> 
  48.         <script type="text/javascript" src="./client.js"></script> 
  49.     </body> 
  50. </html> 

上面的html內容本身沒有什么好說的,我們主要看看里面的4個文件請求:

1、realtime.plhwin.com:3000/socket.io/socket.io.js

2、style.css

3、json3.min.js

4、client.js

第1個JS是Socket.IO提供的客戶端JS文件,在前面安裝服務端的步驟中,當npm安裝完socket.io并搭建起WebServer后,這個JS文件就可以正常訪問了。

第2個style.css文件沒什么好說的,就是樣式文件而已。

第3個JS只在IE8以下版本的IE瀏覽器中加載,目的是讓這些低版本的IE瀏覽器也能處理json,這是一個開源的JS,詳見:http://bestiejs.github.io/json3/

第4個client.js是完整的客戶端的業務邏輯實現代碼,它的內容如下:

  1. (function () { 
  2.     var d = document, 
  3.     w = window, 
  4.     p = parseInt, 
  5.     dd = d.documentElement, 
  6.     db = d.body, 
  7.     dc = d.compatMode == 'CSS1Compat'
  8.     dx = dc ? dd: db, 
  9.     ec = encodeURIComponent; 
  10.      
  11.      
  12.     w.CHAT = { 
  13.         msgObj:d.getElementById("message"), 
  14.         screenheight:w.innerHeight ? w.innerHeight : dx.clientHeight, 
  15.         username:null
  16.         userid:null
  17.         socket:null
  18.         //讓瀏覽器滾動條保持在最低部 
  19.         scrollToBottom:function(){ 
  20.             w.scrollTo(0, this.msgObj.clientHeight); 
  21.         }, 
  22.         //退出,本例只是一個簡單的刷新 
  23.         logout:function(){ 
  24.             //this.socket.disconnect(); 
  25.             location.reload(); 
  26.         }, 
  27.         //提交聊天消息內容 
  28.         submit:function(){ 
  29.             var content = d.getElementById("content").value; 
  30.             if(content != ''){ 
  31.                 var obj = { 
  32.                     userid: this.userid, 
  33.                     username: this.username, 
  34.                     content: content 
  35.                 }; 
  36.                 this.socket.emit('message', obj); 
  37.                 d.getElementById("content").value = ''
  38.             } 
  39.             return false
  40.         }, 
  41.         genUid:function(){ 
  42.             return new Date().getTime()+""+Math.floor(Math.random()*899+100); 
  43.         }, 
  44.         //更新系統消息,本例中在用戶加入、退出的時候調用 
  45.         updateSysMsg:function(o, action){ 
  46.             //當前在線用戶列表 
  47.             var onlineUsers = o.onlineUsers; 
  48.             //當前在線人數 
  49.             var onlineCount = o.onlineCount; 
  50.             //新加入用戶的信息 
  51.             var user = o.user; 
  52.                  
  53.             //更新在線人數 
  54.             var userhtml = ''
  55.             var separator = ''
  56.             for(key in onlineUsers) { 
  57.                 if(onlineUsers.hasOwnProperty(key)){ 
  58.                     userhtml += separator+onlineUsers[key]; 
  59.                     separator = '、'
  60.                 } 
  61.             } 
  62.             d.getElementById("onlinecount").innerHTML = '當前共有 '+onlineCount+' 人在線,在線列表:'+userhtml; 
  63.              
  64.             //添加系統消息 
  65.             var html = ''
  66.             html += '<div class="msg-system">'
  67.             html += user.username; 
  68.             html += (action == 'login') ? ' 加入了聊天室' : ' 退出了聊天室'
  69.             html += '</div>'
  70.             var section = d.createElement('section'); 
  71.             section.className = 'system J-mjrlinkWrap J-cutMsg'
  72.             section.innerHTML = html; 
  73.             this.msgObj.appendChild(section);    
  74.             this.scrollToBottom(); 
  75.         }, 
  76.         //第一個界面用戶提交用戶名 
  77.         usernameSubmit:function(){ 
  78.             var username = d.getElementById("username").value; 
  79.             if(username != ""){ 
  80.                 d.getElementById("username").value = ''
  81.                 d.getElementById("loginbox").style.display = 'none'
  82.                 d.getElementById("chatbox").style.display = 'block'
  83.                 this.init(username); 
  84.             } 
  85.             return false
  86.         }, 
  87.         init:function(username){ 
  88.             /* 
  89.             客戶端根據時間和隨機數生成uid,這樣使得聊天室用戶名稱可以重復。 
  90.             實際項目中,如果是需要用戶登錄,那么直接采用用戶的uid來做標識就可以 
  91.             */ 
  92.             this.userid = this.genUid(); 
  93.             this.username = username; 
  94.              
  95.             d.getElementById("showusername").innerHTML = this.username; 
  96.             this.msgObj.style.minHeight = (this.screenheight - db.clientHeight + this.msgObj.clientHeight) + "px"
  97.             this.scrollToBottom(); 
  98.              
  99.             //連接websocket后端服務器 
  100.             this.socket = io.connect('ws://realtime.plhwin.com:3000'); 
  101.              
  102.             //告訴服務器端有用戶登錄 
  103.             this.socket.emit('login', {userid:this.userid, username:this.username}); 
  104.              
  105.             //監聽新用戶登錄 
  106.             this.socket.on('login'function(o){ 
  107.                 CHAT.updateSysMsg(o, 'login');   
  108.             }); 
  109.              
  110.             //監聽用戶退出 
  111.             this.socket.on('logout'function(o){ 
  112.                 CHAT.updateSysMsg(o, 'logout'); 
  113.             }); 
  114.              
  115.             //監聽消息發送 
  116.             this.socket.on('message'function(obj){ 
  117.                 var isme = (obj.userid == CHAT.userid) ? true : false
  118.                 var contentDiv = '<div>'+obj.content+'</div>'
  119.                 var usernameDiv = '<span>'+obj.username+'</span>'
  120.                  
  121.                 var section = d.createElement('section'); 
  122.                 if(isme){ 
  123.                     section.className = 'user'
  124.                     section.innerHTML = contentDiv + usernameDiv; 
  125.                 } else { 
  126.                     section.className = 'service'
  127.                     section.innerHTML = usernameDiv + contentDiv; 
  128.                 } 
  129.                 CHAT.msgObj.appendChild(section); 
  130.                 CHAT.scrollToBottom();   
  131.             }); 
  132.  
  133.         } 
  134.     }; 
  135.     //通過“回車”提交用戶名 
  136.     d.getElementById("username").onkeydown = function(e) { 
  137.         e = e || event; 
  138.         if (e.keyCode === 13) { 
  139.             CHAT.usernameSubmit(); 
  140.         } 
  141.     }; 
  142.     //通過“回車”提交信息 
  143.     d.getElementById("content").onkeydown = function(e) { 
  144.         e = e || event; 
  145.         if (e.keyCode === 13) { 
  146.             CHAT.submit(); 
  147.         } 
  148.     }; 
  149. })(); 

至此所有的編碼開發工作全部完成了,在瀏覽器中打開http://demo.plhwin.com/chat/就可以看到效果了。

上面所有的客戶端和服務端的代碼可以從Github上獲得,地址:https://github.com/plhwin/nodejs-socketio-chat

git clone https://github.com/plhwin/nodejs-socketio-chat.git

下載本地后有兩個文件夾 clientserverclient文件夾是客戶端源碼,可以放在Nginx/Apache的WebServer中,也可以放在Node.js的WebServer中。后面的server文件夾里的代碼是websocket服務端代碼,放在Node.js環境中,使用npm安裝完 expresssocket.io 后,node index.js 啟動后端服務就可以了。

本例只是一個簡單的Demo,留下2個有關項目擴展的思考:

1、假設是一個在線客服系統,里面有許多的公司使用你的服務,每個公司自己的用戶可以通過一個專屬URL地址進入該公司的聊天室,聊天是一對一的,每個公司可以新建多個客服人員,每個客服人員可以同時和客戶端的多個用戶聊天。

2、又假設是一個在線WebIM系統,實現類似微信,qq的功能,客戶端可以看到好友在線狀態,在線列表,添加好友,刪除好友,新建群組等,消息的發送除了支持基本的文字外,還能支持表情、圖片和文件。

有興趣的同學可以繼續深入研究。

責任編輯:徐川 來源: blog
相關推薦

2013-03-28 14:54:36

2019-07-26 14:40:58

Vue.jsSocket.IO前端

2016-11-22 13:25:28

Apache Spar大數據

2017-09-05 15:30:00

JavascriptSocket.ioNode.js

2014-03-25 14:21:18

WebSocket實時

2024-11-18 17:04:03

Vue3C#

2013-10-23 17:17:31

Node.jsdoT

2012-02-06 10:36:04

Node.js

2023-11-16 14:56:13

2022-02-22 11:39:13

WebSocketsNode.js開發

2012-01-09 13:24:27

2014-10-30 10:28:55

Node.js

2023-11-17 09:35:58

2015-07-15 12:53:05

Node.jsSocket.io遠程控制

2020-10-12 08:06:28

HTTP 服務器證書

2019-05-05 11:47:09

TypeScript開發Node.js

2020-09-04 15:06:04

Docker容器化Node.js

2024-09-02 09:31:19

2015-06-25 12:41:53

實時 Node應用性能監測

2018-08-23 16:18:59

點贊
收藏

51CTO技術棧公眾號

国产不卡一区二区三区在线观看| 亚洲欧美一区二区激情| 成人短视频在线观看免费| 亚洲a视频在线| 鲁大师影院一区二区三区| 一本色道久久88综合亚洲精品ⅰ| 手机精品视频在线| 悠悠资源网亚洲青| 国产精品国产三级国产aⅴ中文| 91视频在线免费观看| 一级黄色大片视频| 亚洲h色精品| 国产丝袜一区二区| 色哟哟免费视频| 成人在线视频播放| 一区二区三区波多野结衣在线观看| 欧美大香线蕉线伊人久久| 亚洲综合精品国产一区二区三区| 亚洲激情不卡| 精品国偷自产在线视频99| 久久久久亚洲AV成人网人人小说| 91欧美精品| 精品久久久久久国产91| 色撸撸在线观看| 可以在线观看的av| 国产精品99久久久久久久女警 | 国产不卡网站| 一区二区在线观看视频| 亚洲日本欧美在线| 欧美日韩在线精品一区二区三区激情综| 黄色精品一二区| 国产精品久久电影观看| 国产午夜久久久| 我不卡手机影院| 国产午夜精品全部视频在线播放| 亚洲av无码一区东京热久久| 国产日韩在线观看视频| 欧美性感一类影片在线播放| 91视频最新入口| 欧美日韩在线视频免费观看| 中文字幕一区二区在线播放| 日韩av一区二区三区美女毛片| 欧美熟妇另类久久久久久不卡 | 日本黄色录像片| 久久三级中文| 69精品人人人人| 国产高潮免费视频| 唐人社导航福利精品| 午夜激情久久久| 亚洲人精品午夜射精日韩| 麻豆网站在线免费观看| 国产三级一区二区| 欧美日韩成人一区二区三区| 午夜小视频在线播放| jiyouzz国产精品久久| 国产精品白丝jk白祙| www.日韩高清| 成人激情校园春色| 国产免费一区二区三区| 天堂在线视频网站| 99re视频精品| 蜜桃av噜噜一区二区三| 你懂的视频在线| 久久嫩草精品久久久精品一| 蜜桃传媒一区二区| 欧美扣逼视频| 国产欧美中文在线| 在线一区高清| www视频在线免费观看| 亚洲精品国产一区二区精华液| 久久久久久久久网| 51漫画成人app入口| 欧美日韩在线视频首页| 国产精品亚洲a| 本网站久久精品| 91精品国产福利| 香蕉视频污视频| 一道在线中文一区二区三区| 一区二区三区四区精品| www深夜成人a√在线| 欧美区一区二| 欧洲美女免费图片一区| 懂色av蜜臀av粉嫩av喷吹| 激情文学综合插| 国产精品日韩欧美一区二区| 男人天堂网在线观看| 亚洲国产激情av| 国产 国语对白 露脸| www视频在线观看| 精品久久久久久| wwwwwxxxx日本| 成人台湾亚洲精品一区二区| 亚洲人成人99网站| 男人晚上看的视频| 在线视频亚洲| 国产在线一区二区三区| 天堂8在线视频| 国产精品色眯眯| 亚洲国产精品成人天堂| 外国电影一区二区| 亚洲第一免费播放区| 国产1区2区在线观看| 欧美三级网页| 国产精品视频1区| 刘亦菲久久免费一区二区| 久久久久九九视频| 国产肉体ⅹxxx137大胆| 中文字幕日本一区二区| 精品国产污网站| 成人午夜免费影院| 国产精品尤物| 成人在线视频电影| 欧洲不卡av| 色综合激情五月| 久久久久无码国产精品一区李宗瑞 | 欧美这里有精品| 熟妇高潮一区二区| 希岛爱理av一区二区三区| 青青草国产精品一区二区| 亚洲av无码乱码国产麻豆| 国产精品嫩草99a| www黄色av| 欧美三级自拍| 欧美区二区三区| 伊人久久亚洲综合| 久久久久久综合| 亚洲 欧美 日韩 国产综合 在线| 国产精品一区二区美女视频免费看| 亚洲人成电影网站色…| 国产成人综合欧美精品久久| 成人午夜免费av| 91大学生片黄在线观看| 日韩成人精品一区二区三区| 亚洲天堂色网站| 成年免费在线观看| 国产.欧美.日韩| 亚洲黄色网址在线观看| 欧美高清免费| 色狠狠久久aa北条麻妃| 欧美成人精品网站| 国产欧美一区二区三区沐欲| 精品国产成人av在线免| 蜜臀久久99精品久久一区二区| 97视频在线免费观看| 亚洲免费成人在线| 亚洲国产综合人成综合网站| zjzjzjzjzj亚洲女人| 亚洲精品网址| 成人av电影免费| 欧美1—12sexvideos| 日韩欧美美女一区二区三区| 九九九在线视频| 高清国产一区二区三区| 欧美日韩福利在线| 国产调教精品| 奇米影视亚洲狠狠色| 性感美女福利视频| 日韩欧美aaa| 亚洲精品成人无码| 日本在线不卡视频一二三区| 亚洲日本japanese丝袜| 伊人久久大香| 欧美精品一区二区三区国产精品| 精品人妻一区二区三区含羞草| 亚洲综合免费观看高清完整版 | 精品淫伦v久久水蜜桃| 性色av香蕉一区二区| 欧美69xxxxx| 欧美视频一区二区三区四区| 欧美h片在线观看| 国产成人综合在线| ww国产内射精品后入国产| 妖精视频一区二区三区| 国产精品一区二区三| av片哪里在线观看| 精品久久久久久综合日本欧美| 全部毛片永久免费看| 国产欧美精品一区aⅴ影院| 牛夜精品久久久久久久| 亚洲先锋影音| 精品一区国产| 国产成+人+综合+亚洲欧美| 久久影视免费观看| 天堂成人在线视频| 欧美日韩在线三级| 国产无套内射又大又猛又粗又爽| 久久久久久久久久久99999| 国产精品久久a| 黄色精品免费| 日韩欧美99| 日韩免费成人| 日韩免费黄色av| 69xxx在线| 亚洲品质视频自拍网| 国产精品久久久久久久一区二区 | 国产毛片毛片毛片毛片| 午夜精品久久久久久久| 黄色激情小视频| av电影天堂一区二区在线观看| 九热视频在线观看| 亚洲国产精品一区| 特级毛片在线免费观看| 色婷婷av一区二区三区丝袜美腿| 成人欧美在线视频| 亚洲天堂电影| 欧美高跟鞋交xxxxhd| 风间由美一区| 亚洲精品福利在线| 精品国产伦一区二区三| 欧洲一区二区三区免费视频| 日本一区二区三区四区五区| 国产精品理论在线观看| 玖草视频在线观看| 国产精品99久久不卡二区| av污在线观看| 久久一区亚洲| 国产伦精品一区二区三区四区视频_| 99精品网站| 日韩欧美一区二区三区四区| 精品伊人久久久| 亚洲最大av在线| 亚洲成人va| 97色伦亚洲国产| 在线电影福利片| xvideos亚洲人网站| 超碰免费在线观看| 日韩高清a**址| 人妻一区二区三区免费| 日韩一区二区三区视频在线 | 美腿丝袜在线亚洲一区 | 国产一区在线视频| 15—17女人毛片| 奇米精品一区二区三区四区| 午夜视频在线瓜伦| 久久精品电影| 岳毛多又紧做起爽| 日韩一区二区免费看| 欧美无砖专区免费| 韩国自拍一区| 国产精品久久久久9999爆乳| 欧美涩涩视频| 欧美久久久久久久久久久久久久| 欧美伊人久久| 日本一区二区三区四区五区六区| 久久精品一区二区不卡| 中文字幕中文字幕一区三区| 五月婷婷亚洲| 女人床在线观看| 欧美精品aa| 97超碰人人澡| 亚洲一区二区三区高清| 男人操女人免费软件| 国产精品久久久久久模特| 俄罗斯av网站| 久久亚洲不卡| 在线观看国产中文字幕| 久久精品二区亚洲w码| 欧美视频亚洲图片| 国产成人三级在线观看| 初高中福利视频网站| 成人av第一页| 国产三级国产精品| 国产免费久久精品| 欧美三级黄色大片| 亚洲一区在线观看网站| 欧美成人aaaaⅴ片在线看| 欧美日韩加勒比精品一区| 精品黑人一区二区三区| 欧美探花视频资源| 国产婷婷在线视频| 精品99999| 国产高清视频免费最新在线| 日韩日本欧美亚洲| 久久一卡二卡| 奇米影视亚洲狠狠色| 色综合.com| 国产精品美女久久久久av福利| 美女呻吟一区| 色综合久久av| 欧美日本中文| 国产裸体舞一区二区三区 | 精品国产一二区| 91麻豆免费看片| 永久免费看片视频教学| 亚洲一区在线观看免费观看电影高清| 亚洲天堂视频网站| 777久久久精品| 手机亚洲第一页| 日韩小视频在线观看| www.超碰在线| 成人欧美一区二区三区黑人| 啪啪国产精品| a级网站在线观看| 免费看的黄色欧美网站| 久久精品国产露脸对白| 91女人视频在线观看| 免费三级在线观看| 色综合久久久久网| www.天天干.com| 伊人亚洲福利一区二区三区| 丁香花电影在线观看完整版| 国产精品久久久亚洲| 风间由美性色一区二区三区四区| 日本一区二区三区精品视频| 国产精品videossex久久发布| 黑人粗进入欧美aaaaa| 成人一区二区三区视频| 黄色国产在线播放| 欧美视频一二三| 成人av一区二区三区在线观看 | 色呦呦视频在线观看| 国产成人精品免高潮费视频| 国产精品玖玖玖在线资源| 一级特黄录像免费播放全99| 国产精品日韩欧美一区| 宇都宫紫苑在线播放| 久久亚洲春色中文字幕久久久| 欧美黄色免费在线观看| 欧美欧美午夜aⅴ在线观看| 青青草视频免费在线观看| 欧美精品videossex88| 亚洲精品大片| 日韩欧美亚洲日产国| 奶水喷射视频一区| 久久久久久久久久久久国产精品| 成人欧美一区二区三区视频网页| 中文字幕一区二区三区四区视频| 亚洲免费高清视频| 国产自产自拍视频在线观看| 国产高清自拍一区| 欧美日韩久久| 日本中文字幕在线不卡| 亚洲欧美自拍偷拍色图| 这里只有精品6| 深夜福利一区二区| 日本一区二区三区视频在线| 欧美日韩在线一二三| 免播放器亚洲| 51妺嘿嘿午夜福利| 在线精品视频免费观看| 韩日在线视频| 国产精品爱啪在线线免费观看| 蜜臀91精品国产高清在线观看| 欧美女人性生活视频| 久久综合成人精品亚洲另类欧美 | 久久av资源网| 任我爽在线视频| 91精品国产手机| 香蕉成人app免费看片| 91av免费看| 影音先锋日韩资源| 国产精品成人99一区无码| 五月天婷婷综合| 色综合888| 国产精品国产福利国产秒拍| 成人免费av| 想看黄色一级片| 亚洲综合久久av| 黄色片一区二区三区| 992tv在线成人免费观看| 亚洲精华一区二区三区| 国产精品天天av精麻传媒| 国产精品毛片a∨一区二区三区| 一级成人免费视频| 久久久成人av| 高清日韩中文字幕| 午夜肉伦伦影院| 国产精品欧美极品| 精品黑人一区二区三区国语馆| 欧美精品成人91久久久久久久| 日韩一级电影| 婷婷丁香激情网| 一区二区三区精密机械公司| 天堂在线免费av| 国产精品日韩电影| 欧美日韩专区| 性欧美成人播放77777| 欧美日韩精品电影| 日韩激情美女| 欧美一区二区三区成人久久片| 激情偷乱视频一区二区三区| av大片免费在线观看| 中文字幕亚洲综合久久| 99久热这里只有精品视频免费观看| 欧美a v在线播放| 亚洲少妇30p| 国产 欧美 自拍| 国产精品99蜜臀久久不卡二区| 亚洲情侣在线| 毛茸茸多毛bbb毛多视频| 欧美喷潮久久久xxxxx| 国产美女高潮在线| 亚洲在线播放电影| 99国产精品久久久久久久久久| 一级aaaa毛片| 欧美一级黑人aaaaaaa做受| 亚洲国产精品久久久天堂| 国产黄色三级网站| 欧美一区二区三区色| 三级成人黄色影院|