精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美成人一区二区三区高清| 红桃av在线播放| 国产高潮在线观看| 亚洲高清激情| 亚洲午夜av久久乱码| 日韩大片一区二区| 青青青国内视频在线观看软件| proumb性欧美在线观看| 国产成人精品免高潮费视频| 国产黄色录像片| 狠狠久久伊人| 欧美丝袜丝nylons| av动漫在线播放| 欧美色图另类| 国产美女一区二区| 97久久久久久| 任我爽在线视频| 牛牛影视一区二区三区免费看| 在线观看国产精品网站| 无码人妻精品一区二区蜜桃网站| 蜜芽tv福利在线视频| 国产乱子伦视频一区二区三区| 日韩av电影国产| 免费网站看av| 日韩中文欧美| 国产视频自拍一区| 91精品国产高清91久久久久久| 黄瓜视频成人app免费| 亚洲精品免费一二三区| 日韩不卡av| 天天操天天干天天爱| 国精产品一区一区三区mba桃花 | 国产精品久久久久久久久久直播| 伊人中文字幕在线观看 | 国产三级精品三级| 国产91亚洲精品一区二区三区| 中文字幕一区二区在线视频| 国产农村妇女精品一二区| 久久91亚洲精品中文字幕奶水| 99精品欧美一区二区| 四虎884aa成人精品最新| 日韩精品一区二区三区在线播放| 中日韩av在线播放| 欧美国产日韩电影| 日韩欧美亚洲国产一区| 97干在线视频| 中文在线免费| 亚洲欧美日韩人成在线播放| 先锋影音日韩| 国产网站在线播放| 国产亲近乱来精品视频| 欧美极品jizzhd欧美| 日韩二区三区| 久久免费美女视频| 精品免费视频123区| 日本高清视频www| 高清视频一区二区| 国产精品国产亚洲精品看不卡15| 亚洲第一黄色片| 国产成人亚洲精品青草天美| 亚洲综合色av| 亚洲国产成人一区二区| 懂色av一区二区三区蜜臀| 91久久伊人青青碰碰婷婷| www.久久成人| 成人教育av在线| 久久国产精品高清| 欧美另类自拍| 国产精品免费免费| 在线视频不卡一区二区三区| 超碰免费公开在线| 亚洲一区二区三区影院| av7777777| 欧美日韩在线精品一区二区三区激情综合 | 久久se这里有精品| 成人欧美一区二区三区在线湿哒哒| 91久久精品国产91久久性色tv | 欧美性猛交xx| 99这里只有精品视频| 亚洲国产精品专区久久| 美女又爽又黄视频毛茸茸| 欧美**vk| 久久精品国产清自在天天线 | 久久丫精品国产亚洲av不卡| 国产一区二区三区日韩精品| 色噜噜久久综合伊人一本| 天天操天天操天天操天天操天天操| 国产精品www.| 日韩美女免费线视频| 亚洲天堂自拍偷拍| 成人看片黄a免费看在线| 久久久一本精品99久久精品| 在线视频自拍| 亚洲自拍另类综合| 国产无套粉嫩白浆内谢的出处| 欧美亚洲黄色| 精品成人在线观看| jizz中文字幕| 欧美国产高潮xxxx1819| 欧美一二三视频| 国产精品久久久久精| 99国产精品久久久久| 亚洲一区二区三区免费看| 黑人极品ⅴideos精品欧美棵| 色婷婷狠狠综合| 精品人妻一区二区免费| 狠狠综合久久av一区二区蜜桃| 久久精品亚洲94久久精品| 国产超碰人人爽人人做人人爱| 久久精品国产久精国产爱| 九九九九精品九九九九| 国产一级片黄色| 免费在线观看一区| 欧美成人精品1314www| 男女做爰猛烈刺激| 黄色欧美日韩| 国产原创欧美精品| 日本大片在线观看| 亚洲自拍偷拍网站| 天天操精品视频| 国产精品美女毛片真酒店| 婷婷亚洲综合| 日韩美女视频在线观看| 蜜臀av在线观看| 中文字幕亚洲不卡| 国产一区二区视频免费在线观看| 欧美久久亚洲| 色偷偷88888欧美精品久久久| 免费在线不卡视频| 国产99久久久精品| 一区二区免费电影| 2019年精品视频自拍| 精品无人国产偷自产在线| 青青草在线观看视频| 久久精品国产亚洲一区二区三区 | 日产精品一区二区| 欧美有码在线观看视频| 欧美一区二区黄片| 一片黄亚洲嫩模| 美女被爆操网站| 一区二区不卡| 91精品在线一区| 在线视频婷婷| 欧美另类z0zxhd电影| 国产探花视频在线播放| 三级欧美韩日大片在线看| 国产一区二区精品免费| av老司机在线观看| 亚洲国内高清视频| 91午夜视频在线观看| 成人免费观看男女羞羞视频| 800av在线免费观看| 97视频一区| 午夜精品理论片| 四虎影视2018在线播放alocalhost| 亚洲444eee在线观看| 欧美在线一级片| 国精品人妻无码一区二区三区喝尿 | 欧美视频亚洲图片| 久久在线视频| 成人在线激情视频| www.欧美日本韩国| 日韩一区二区精品在线观看| 波多野结衣家庭教师| 国产一区二区0| 日本精品福利视频| 国产色噜噜噜91在线精品| 久久久爽爽爽美女图片| 四虎精品成人免费网站| 欧美亚洲愉拍一区二区| 日本爱爱小视频| 国产69精品久久99不卡| 黄页免费在线观看视频| 蜜桃a∨噜噜一区二区三区| 国产精品欧美日韩久久| 菠萝菠萝蜜在线视频免费观看| 欧美大肚乱孕交hd孕妇| 亚洲第一精品在线观看| 久久精品在这里| 红桃视频 国产| 亚洲经典自拍| 亚洲欧洲在线一区| 欧一区二区三区| 欧美最猛黑人xxxx黑人猛叫黄| p色视频免费在线观看| 日韩视频永久免费| 国产又黄又粗又爽| 中国av一区二区三区| 欧美性猛交xx| 亚洲永久视频| 欧美 日韩 国产 在线观看| 成人在线视频中文字幕| 国产精品福利网站| 色呦呦网站在线观看| 亚洲美女自拍视频| 99国产揄拍国产精品| 岛国av午夜精品| 麻豆天美蜜桃91| 久久精品这里都是精品| 少妇献身老头系列| 日本伊人色综合网| 日本一本中文字幕| 日韩综合一区| 精品国产乱码久久久久软件| 久久91视频| 欧美怡春院一区二区三区| 超碰在线caoporn| 在线不卡国产精品| 日韩中文字幕影院| 欧美精品国产白浆久久久久| 2019中文字幕在线观看| 精品176二区| 亚洲区中文字幕| 亚洲a视频在线观看| 欧美私模裸体表演在线观看| 亚洲欧美精品一区二区三区| 亚洲欧美日韩国产一区二区三区 | 久久99精品久久久久久噜噜| 高清美女视频一区| 亚洲成人久久一区| 国产喷水福利在线视频| 欧美在线一区二区三区| 国产视频91在线| 亚洲一区二区高清| 91插插插插插插| 国产精品视频一二三区| 37p粉嫩大胆色噜噜噜| 成人免费视频播放| 少妇丰满尤物大尺度写真| 蜜桃视频在线观看一区| 黄色一级大片在线观看| 亚洲少妇诱惑| 免费在线观看视频a| 欧美女人交a| 欧美一级免费在线观看| 婷婷综合社区| 香蕉久久夜色| 久久香蕉国产| 亚洲精品一区二区毛豆| 成久久久网站| 日本一区视频在线播放| 视频国产一区| 日本亚洲欧洲精品| 国产探花一区在线观看| 欧美一级二级三级| 九九久久电影| 欧美少妇一区| 日产精品一区二区| 欧美 日韩 国产 在线观看| 久久视频精品| 视频一区二区视频| 亚洲一区色图| 黄色一级片国产| 激情综合电影网| 1024av视频| 久久婷婷丁香| 韩国中文字幕av| 久久99精品国产麻豆不卡| 97超碰人人爽| 国产白丝精品91爽爽久久| 一级黄色免费视频| 91啪九色porn原创视频在线观看| 我和岳m愉情xxxⅹ视频| 国产亚洲欧美中文| 精品国内产的精品视频在线观看| 黄色av中文字幕| 日韩成人在线网站| 国产精品天堂| 日韩中文在线中文网在线观看| 免费黄色在线看| 欧美激情视频免费观看| 美女网站在线看| 国产精品91免费在线| 视频欧美精品| 国产精品香蕉视屏| 欧美日韩直播| 日韩在线三区| 欧美大片专区| 韩国日本在线视频| 韩国理伦片一区二区三区在线播放 | 中文字幕人成乱码在线观看| 国产精品69久久久久| aa亚洲一区一区三区| 国产精品一区二区三区免费观看| 竹菊久久久久久久| 欧美日韩在线免费观看视频| 国产人成精品一区二区三| 欧美婷婷精品激情| 国产成人亚洲综合a∨婷婷图片| 日韩av在线看免费观看| 亚洲特级片在线| 九九热精品视频在线| 欧美精三区欧美精三区| 婷婷在线免费视频| 色伦专区97中文字幕| а√天堂8资源中文在线| 国产精品一区二区三区在线播放| 超碰在线成人| 亚洲视频电影| 老鸭窝毛片一区二区三区| 三级一区二区三区| 97久久超碰国产精品| 疯狂撞击丝袜人妻| 福利视频一区二区| 99视频在线观看免费| 亚洲欧美在线第一页| 青草视频在线免费直播 | 国产淫片免费看| 国产一区二区三区在线观看免费视频 | 91专区在线观看| 精品一二线国产| 日韩精品无码一区二区三区久久久 | 激情av综合网| 无码少妇精品一区二区免费动态| 99精品美女| 奇米四色中文综合久久| 欧美国产视频| 欧洲久久久久久| 在线综合视频| 日本少妇一级片| 亚洲天堂2016| 夜夜嗨av禁果av粉嫩avhd| 亚洲欧美日韩一区二区在线 | 精品视频日韩| 欧美性大战久久久久xxx| 成人国产亚洲欧美成人综合网| 顶臀精品视频www| 欧美日本一道本在线视频| 欧美少妇另类| 日本一区二区不卡| 亚洲精品动态| 国产91对白刺激露脸在线观看| 丰满少妇久久久久久久| 三级影片在线看| 欧美精品三级日韩久久| av在线播放网站| 国产精品99久久久久久久久久久久| 日本欧美韩国国产| 免费成人在线视频网站| 99精品一区二区三区| 黄色激情视频在线观看| 亚洲精品一区二区三区香蕉| 欧美人体视频xxxxx| 91九色偷拍| 激情欧美国产欧美| 亚洲久久久久久| 疯狂做受xxxx高潮欧美日本| 视频一区二区三区在线看免费看| 97在线观看视频| 午夜精品福利影院| 欧美韩国日本在线| 久久精品人人做人人爽人人| 欧美一区免费看| 一夜七次郎国产精品亚洲| 成人午夜在线| 宅男一区二区三区| 国产精品影视天天线| 18精品爽视频在线观看| 亚洲国产精品va在线看黑人动漫 | 午夜在线小视频| 成人信息集中地欧美| 欧美精选在线| 无码人妻aⅴ一区二区三区| 日本韩国精品在线| 老司机福利在线视频| 91成人理论电影| 国产情侣久久| 东京热无码av男人的天堂| 91精品婷婷国产综合久久 | 国产91色在线|| 日韩欧美精品一区| 91av免费观看| 欧美午夜激情在线| 天堂а√在线资源在线| 91精品国产综合久久男男| 午夜激情一区| 不卡一区二区在线观看| 欧美色综合网站| 欧美性受ⅹ╳╳╳黑人a性爽| 亚洲精品久久久久久久久| 日韩免费不卡视频| 亚洲国产精品国自产拍av秋霞| 日韩大片欧美大片| 最新不卡av| 99精品热视频| 91国内精品视频| 午夜精品久久17c| 欧美国产一级| 国产黑丝在线观看| 欧美亚洲国产一卡| 美女精品导航| 亚洲二区自拍| av电影在线观看不卡| 伊人久久一区二区| 国内精品久久久久影院优 | 中国女人做爰视频| 久久久久久一级片| www.com在线观看| 国产精品久久久久久久app| 欧美视频久久|