亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

html5服務器推送_動力節點Java學院整理

2024-08-26 00:19:45
字體:
來源:轉載
供稿:網友

對于一般的 Web 應用開發,大多數開發人員并不陌生。在 Web 應用中,瀏覽器和服務器之間使用的是請求 / 響應的交互模式。瀏覽器發出請求,服務器根據收到的請求來生成相應的響應。瀏覽器再對收到的響應進行處理,展現給用戶。響應的格式可能是 HTML、XML 或 JSON 等。隨著 REST 架構風格和 AJAX 的流行,服務器更多地使用 JSON 作為響應的數據格式。Web 應用使用 XMLHttpRequest 對象來發送請求,并根據服務器端返回的數據,對頁面的內容進行動態更新。通常來說,用戶在頁面上的操作,比如點擊或移動鼠標,會觸發相應的事件。由 XMLHttpRequest 對象來發出請求,得到服務器響應之后進行頁面的局部更新。這種方式的不足之處在于:服務器端產生的數據變化不能及時地通知瀏覽器,而是需要等到下次請求發出時才能被瀏覽器獲取。對于某些對數據實時性要求很高的應用來說,這種延遲是不能接受的。為了滿足這類應用的需求,就需要有某種方式能夠從服務器端推送數據給瀏覽器,以保證服務器端的數據變化可以在第一時間通知給用戶。目前常見的解決辦法有不少,主要可以分成兩類。這兩類方法的區別在于是否基于 HTTP 協議來實現。不使用 HTTP 協議的做法是使用 HTML 5 新增的 WebSocket 規范,而使用 HTTP 協議的做法則包括簡易輪詢、COMET 技術和本文中要介紹的 HTML 5 服務器推送事件。下面會對這幾種技術進行介紹。

簡介

在介紹 HTML 5 服務器推送事件之前,首先介紹一些上面提到的幾種服務器端數據推送技術。第一種是 WebSocket。WebSocket 規范是 HTML 5 中的一個重要組成部分,已經被很多主流瀏覽器所支持,也有不少基于 WebSocket 開發的應用。正如名稱所表示的一樣,WebSocket 使用的是套接字連接,基于 TCP 協議。使用 WebSocket 之后,實際上在服務器端和瀏覽器之間建立一個套接字連接,可以進行雙向的數據傳輸。WebSocket 的功能是很強大的,使用起來也靈活,可以適用于不同的場景。不過 WebSocket 技術也比較復雜,包括服務器端和瀏覽器端的實現都不同于一般的 Web 應用。

除了 WebSocket 之外,其他的實現方式是基于 HTTP 協議來達到實時推送的效果。第一種做法是簡易輪詢,即瀏覽器端定時向服務器端發出請求,來查詢是否有數據更新。這種做法比較簡單,可以在一定程度上解決問題。不過對于輪詢的時間間隔需要進行仔細考慮。輪詢的間隔過長,會導致用戶不能及時接收到更新的數據;輪詢的間隔過短,會導致查詢請求過多,增加服務器端的負擔。

COMET 技術改進了簡易輪詢的缺點,使用的是長輪詢。長輪詢的方式在每次請求時,服務器端會保持該連接在一段時間內處于打開狀態,而不是在響應完成之后就立即關閉。這樣做的好處是在連接處于打開狀態的時間段內,服務器端產生的數據更新可以被及時地返回給瀏覽器。當上一個長連接關閉之后,瀏覽器會立即打開一個新的長連接來繼續請求。不過 COMET 技術的實現在服務器端和瀏覽器端都需要第三方庫的支持。綜合比較上面提到的 4 種不同的技術,簡易輪詢由于其本身的缺陷,并不推薦使用。COMET 技術并不是 HTML 5 標準的一部分,從兼容標準的角度出發,也不推薦使用。WebSocket 規范和服務器推送技術都是 HTML 5 標準的組成部分,在主流瀏覽器上都提供了原生的支持,是推薦使用的。不過 WebSocket 規范更加復雜一些,適用于需要進行復雜雙向數據通訊的場景。對于簡單的服務器數據推送的場景,使用服務器推送事件就足夠了。

在瀏覽器支持方面,服務器推送事件已經在除 IE 外的大部分桌面和移動瀏覽器上得到了支持。支持服務器推送事件的瀏覽器及其版本包括:Firefox 6.0+、Chrome 6.0+、Safari 5.0+、Opera 11.0+、iOS Safari 4.0+、Opera Mobile 11.1+、Chrome for Android 25.0+、Firefox for Android 19.0+ 以及 Blackberry Browser 7.0+ 等。關于 IE 的支持,在下面的章節中有詳細的介紹。

下面對服務器推送事件的規范進行具體的說明。

規范

Server-sent Events 規范是 HTML 5 規范的一個組成部分,具體的規范文檔見參考資源。該規范比較簡單,主要由兩個部分組成:第一個部分是服務器端與瀏覽器端之間的通訊協議,第二部分則是在瀏覽器端可供 JavaScript 使用的 EventSource 對象。通訊協議是基于純文本的簡單協議。服務器端的響應的內容類型是“text/event-stream”。響應文本的內容可以看成是一個事件流,由不同的事件所組成。每個事件由類型和數據兩部分組成,同時每個事件可以有一個可選的標識符。不同事件的內容之間通過僅包含回車符和換行符的空行(“/r/n”)來分隔。每個事件的數據可能由多行組成。代碼清單 1 給出了服務器端響應的示例。

服務器端響應的示例

data: first eventdata: second eventid: 100event: myeventdata: third eventid: 101: this is a commentdata: fourth eventdata: fourth event continue

如代碼清單 1 所示,每個事件之間通過空行來分隔。對于每一行來說,冒號(“:”)前面表示的是該行的類型,冒號后面則是對應的值??赡艿念愋桶ǎ?/p>

  1. 類型為空白,表示該行是注釋,會在處理時被忽略。
  2. 類型為 data,表示該行包含的是數據。以 data 開頭的行可以出現多次。所有這些行都是該事件的數據。
  3. 類型為 event,表示該行用來聲明事件的類型。瀏覽器在收到數據時,會產生對應類型的事件。
  4. 類型為 id,表示該行用來聲明事件的標識符。
  5. 類型為 retry,表示該行用來聲明瀏覽器在連接斷開之后進行再次連接之前的等待時間。

在上面代碼中,第一個事件只包含數據“first event”,會產生默認的事件;第二個事件的標識符是 100,數據為“second event”;第三個事件會產生類型為“myevent”的事件;最后一個事件的數據為“fourth event/nfourth event continue”。當有多行數據時,實際的數據由每行數據以換行符連接而成。

如果服務器端返回的數據中包含了事件的標識符,瀏覽器會記錄最近一次接收到的事件的標識符。如果與服務器端的連接中斷,當瀏覽器端再次進行連接時,會通過 HTTP 頭“Last-Event-ID”來聲明最后一次接收到的事件的標識符。服務器端可以通過瀏覽器端發送的事件標識符來確定從哪個事件開始來繼續連接。

對于服務器端返回的響應,瀏覽器端需要在 JavaScript 中使用 EventSource 對象來進行處理。EventSource 使用的是標準的事件監聽器方式,只需要在對象上添加相應的事件處理方法即可。EventSource 提供了三個標準事件,如表 1 所示。

表 1. EventSource 對象提供的標準事件

 

名稱
說明
事件處理方法
open
當成功與服務器建立連接時產生
onopen
message
當收到服務器發送的事件時產生
onmessage
error
當出現錯誤時產生
onerror

 

如之前所述,服務器端可以返回自定義類型的事件。對于這些事件,可以使用 addEventListener 方法來添加相應的事件處理方法。代碼清單 2 給出了 EventSource 對象的使用示例。

EventSource 對象的使用示例

var es = new EventSource('events');es.onmessage = function(e) {    console.log(e.data);};es.addEventListener('myevent', function(e) {    console.log(e.data);});

如上所示,在指定 URL 創建出 EventSource 對象之后,可以通過 onmessage 和 addEventListener 方法來添加事件處理方法。當服務器端有新的事件產生,相應的事件處理方法會被調用。EventSource 對象的 onmessage 屬性的作用類似于 addEventListener( ‘ message ’ ),不過 onmessage 屬性只支持一個事件處理方法。在介紹完服務器推送事件的規范內容之后,下面介紹服務器端的實現。

服務器端和瀏覽器端實現

從上一節中對通訊協議的描述可以看出,服務器端推送事件是一個比較簡單的協議。服務器端的實現也相對比較簡單,只需要按照協議規定的格式,返回響應內容即可。在開源社區可以找到各種不同的服務器端技術相對應的實現。自己開發的難度也不大。本文使用 Java 作為服務器端的實現語言。相應的實現基于開源的 jetty-eventsource-servlet 項目,見參考資源。下面通過一個具體的示例來說明如何使用 jetty-eventsource-servlet 項目。示例用來模擬一個物體在某個限定空間中的隨機移動。該物體從一個隨機位置開始,然后從上、下、左和右四個方向中隨機選擇一個方向,并在該方向上移動隨機的距離。服務器端不斷改變該物體的位置,并把位置信息推送給瀏覽器,由瀏覽器來顯示。

服務器端實現

服務器端的實現由兩部分組成:一部分是用來產生數據的 org.eclipse.jetty.servlets.EventSource 接口的實現,另一部分是作為瀏覽器訪問端點的繼承自 org.eclipse.jetty.servlets.EventSourceServlet 類的 servlet 實現。下面代碼給出了 EventSource 接口的實現類。

EventSource 接口的實現類 MovementEventSource

 public class MovementEventSource implements EventSource {  private int width = 800; private int height = 600; private int stepMax = 5; private int x = 0; private int y = 0; private Random random = new Random(); private Logger logger = Logger.getLogger(getClass().getName());  public MovementEventSource(int width, int height, int stepMax) {  this.width = width;  this.height = height;  this.stepMax = stepMax;  this.x = random.nextInt(width);  this.y = random.nextInt(height); } @Override public void onOpen(Emitter emitter) throws IOException {  query(emitter); //開始生成位置信息 } @Override public void onResume(Emitter emitter, String lastEventId)   throws IOException {  updatePosition(lastEventId); //更新起始位置  query(emitter);  //開始生成位置信息 }  //根據Last-Event-Id來更新起始位置 private void updatePosition(String id) {  if (id != null) {   String[] pos = id.split(",");   if (pos.length > 1) {    int xPos = -1, yPos = -1;    try {     xPos = Integer.parseInt(pos[0], 10);     yPos = Integer.parseInt(pos[1], 10);    } catch (NumberFormatException e) {         }    if (isValidMove(xPos, yPos)) {     x = xPos;     y = yPos;    }   }  } }  private void query(Emitter emitter) throws IOException {  emitter.comment("Start sending movement information.");  while(true) {   emitter.comment("");   move(); //移動位置   String id = String.format("%s,%s", x, y);   emitter.id(id); //根據位置生成事件標識符   emitter.data(id); //發送位置信息數據   try {    Thread.sleep(2000);   } catch (InterruptedException e) {    logger.log(Level.WARNING, /               "Movement query thread interrupted. Close the connection.", e);    break;   }  }  emitter.close(); //當循環終止時,關閉連接 } @Override public void onClose() {   }  //獲取下一個合法的移動位置 private void move() {  while (true) {   int[] move = getMove();   int xNext = x + move[0];   int yNext = y + move[1];   if (isValidMove(xNext, yNext)) {    x = xNext;    y = yNext;    break;   }  } } //判斷當前的移動位置是否合法 private boolean isValidMove(int x, int y) {  return x >= 0 && x <= width && y >=0 && y <= height; }  //隨機生成下一個移動位置 private int[] getMove() {  int[] xDir = new int[] {-1, 0, 1, 0};  int[] yDir = new int[] {0, -1, 0, 1};  int dir = random.nextInt(4);  return new int[] {xDir[dir] * random.nextInt(stepMax), /     yDir[dir] * random.nextInt(stepMax)}; }}

類 MovementEventSource 需要實現 EventSource 接口的 onOpen、onResume 和 onClose 方法,其中 onOpen 方法在瀏覽器端的連接打開的時候被調用,onResume 方法在瀏覽器端重新建立連接時被調用,onClose 方法則在瀏覽器關閉連接的時候被調用。onOpen 和 onResume 方法都有一個 EventSource.Emitter 接口類型的參數,可以用來發送數據。EventSource.Emitter 接口中包含的方法包括 data、event、comment、id 和 close 等,分別對應于通訊協議中各種不同類型的事件。而 onResume 方法還額外包含一個參數 lastEventId,表示通過 Last-Event-ID 頭發送過來的最近一次事件的標識符。

MovementEventSource 類中事件生成的主要邏輯在 query 方法中。該方法中包含一個無限循環,每隔 2 秒鐘改變一次位置,同時把更新之后的位置通過 EventSource.Emitter 接口的 data 方法發送給瀏覽器端。每個事件都有對應的標識符,而標識符的值就是位置本身。如果連接斷開之后,瀏覽器重新進行連接,可以從上一次的位置開始繼續移動該物體。

與 MovementEventSource 類對應的 servlet 實現比較簡單,只需要繼承自 EventSourceServlet 類并覆寫 newEventSource 方法即可。在 newEventSource 方法的實現中,需要返回一個 MovementEventSource 類的對象,如下所示。每當瀏覽器端建立連接時,該 servlet 會創建一個新的 MovementEventSource 類的對象來處理該請求。

servlet 實現類 MovementServlet

 public class MovementServlet extends EventSourceServlet {  @Override  protected EventSource newEventSource(HttpServletRequest request,  String clientId) {  return new MovementEventSource(800, 600, 20);  }  }

在服務器端實現中,需要注意的是要添加相應的 servlet 過濾器支持。這是 jetty-eventsource-servlet 項目所依賴的 Jetty Continuations 框架的要求,否則的話會出現錯誤。添加過濾器的方式是在 web.xml 文件中添加代碼如下所示的配置內容。

Jetty Continuations 所需 servlet 過濾器的配置

 <filter>     <filter-name>continuation</filter-name>     <filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>  </filter>  <filter-mapping>     <filter-name>continuation</filter-name>     <url-pattern>/sse/*</url-pattern>  </filter-mapping>

瀏覽器端實現

瀏覽器端的實現也比較簡單,只需要創建出 EventSource 對象,并添加相應的事件處理方法即可。下面代碼給出了相應的實現。在頁面中使用一個方塊表示物體。當接收到新的事件時,根據事件數據中給出的坐標信息,更新方塊在頁面上的位置。

瀏覽器端的實現代碼

 var es = new EventSource('sse/movement');  es.addEventListener('message', function(e) {      var pos = e.data.split(','), x = pos[0], y = pos[1];      $('#box').css({          left : x + 'px',          top : y + 'px'          });      });

在介紹完基本的服務器端和瀏覽器端實現之后,下面介紹比較重要的 IE 的支持。

IE 支持

使用瀏覽器原生的 EventSource 對象的一個比較大的問題是 IE 并不提供支持。為了在 IE 上提供同樣的支持,一般有兩種辦法。第一種辦法是在其他瀏覽器上使用原生 EventSource 對象,而在 IE 上則使用簡易輪詢或 COMET 技術來實現;另外一種做法是使用 polyfill 技術,即使用第三方提供的 JavaScript 庫來屏蔽瀏覽器的不同。本文使用的是 polyfill 技術,只需要在頁面中加載第三方 JavaScript 庫即可。應用本身的瀏覽器端代碼并不需要進行改動。一般推薦使用第二種做法,因為這樣的話,在服務器端只需要使用一種實現技術即可。

在 IE 上提供類似原生 EventSource 對象的實現并不簡單。理論上來說,只需要通過 XMLHttpRequest 對象來獲取服務器端的響應內容,并通過文本解析,就可以提取出相應的事件,并觸發對應的事件處理方法。不過問題在于 IE 上的 XMLHttpRequest 對象并不支持獲取部分的響應內容。只有在響應完成之后,才能獲取其內容。由于服務器端推送事件使用的是一個長連接。當連接一直處于打開狀態時,通過 XMLHttpRequest 對象并不能獲取響應的內容,也就無法觸發對應的事件。更具體的來說,當 XMLHttpRequest 對象的 readyState 為 3(READYSTATE_INTERACTIVE)時,其 responseText 屬性是無法獲取的。

為了解決 IE 上 XMLHttpRequest 對象的問題,就需要使用 IE 8 中引入的 XDomainRequest 對象。XDomainRequest 對象的作用是發出跨域的 AJAX 請求。XDomainRequest 對象提供了 onprogress 事件。當 onprogress 事件發生時,可以通過 responseText 屬性來獲取到響應的部分內容。這是 XDomainRequest 對象和 XMLHttpRequest 對象的最大不同,也是使用 XDomainRequest 對象來實現類似原生 EventSource 對象的基礎。在使用 XDomainRequest 對象打開與服務器端的連接之后,當服務器端有新的數據產生時,可以通過 XDomainRequest 對象的 onprogress 事件的處理方法來進行處理,對接收到的數據進行解析,根據數據的內容觸發相應的事件。

不過由于 XDomainRequest 對象本來的目的是發出跨域 AJAX 請求,考慮到跨域訪問的安全性問題,XDomainRequest 對象在使用時的限制也比較嚴格。這些限制會影響到其作為 EventSource 對象的實現方式。具體的限制和解決辦法如下所示:

  1. 服務器端的響應需要包含 Access-Control-Allow-Origin 頭,用來聲明允許從哪些域訪問該 URL。“*”表示允許來自任何域的訪問,不推薦使用該值。一般使用與當前應用相同的域,限制只允許來自當前域的訪問。
  2. XDomainRequest 對象發出的請求不能包含自定義的 HTTP 頭,這就限制了不能使用 Last-Event-ID 頭來聲明瀏覽器端最近一次接收到的事件的標識符。只能通過 HTTP 請求的其他方式來傳遞該標識符,如 GET 請求的參數或 POST 請求的內容體。
  3. XDomainRequest 對象的請求的內容類型(Content-Type)只能是“text/plain”。這就意味著,當使用 POST 請求時,服務器端使用的框架,如 servlet,不會對 POST 請求的內容進行自動解析,無法使用 HttpServletRequest 類的 getParameter 方法來獲取 POST 請求的內容。只能在服務器端對原始的請求內容進行解析,獲取到其中的參數的值。
  4. XDomainRequest 對象發出的請求中不包含任何與用戶認證相關的信息,包括 cookie 等。這就意味著,如果服務器端需要認證,則需要通過 HTTP 請求的其他方式來傳遞用戶的認證信息,比如 session 的 ID 等。

由于 XDomainRequest 對象的這些限制,服務器端的實現也需要作出相應的改動。這些改動包括返回 Access-Control-Allow-Origin 頭;對于瀏覽器端發送的“text/plain”類型的參數進行解析;處理請求中包含的用戶認證相關的信息。

本文的示例使用的 polyfill 庫是 GitHub 上的 Yaffle 開發的 EventSource 項目,具體的地址見參考資源。在使用該 polyfill 庫,并對服務器端的實現進行修改之后,就可以在 IE 8 及以上的瀏覽器中使用服務器推送事件。如果需要支持 IE 7,則只能使用簡易輪詢或 COMET 技術。本文的示例代碼見參考資源。

小結

如果需要從服務器端推送數據給瀏覽器,可以使用的基于 HTML 5 規范標準的技術包括 WebSocket 和服務器推送事件。開發人員可以根據應用的具體需求來選擇合適的技術。如果只是需要從服務器端推送數據,服務器推送事件的規范更加簡單,實現起來更容易。本文對服務器推送事件的規范內容、服務器端和瀏覽器端的實現都進行了詳細的介紹,對如何支持 IE 瀏覽器也進行了具體的分析。


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91久久精品国产91性色| 欧美一级bbbbb性bbbb喷潮片| 日韩欧美精品免费在线| 97在线视频观看| 久久久精品日本| 久久综合国产精品台湾中文娱乐网| 久久九九精品99国产精品| 国产成人av在线播放| 久久成人18免费网站| 日韩av在线一区二区| 亚洲第一页中文字幕| 久久久久久久久久久免费| 久久久国产精品一区| 欧美日韩中文字幕在线| 91久久国产婷婷一区二区| 成人淫片在线看| 琪琪第一精品导航| 精品一区二区三区四区在线| 国产亚洲美女精品久久久| 欧美日韩中文字幕在线视频| 国产精品99久久久久久www| 日韩免费在线看| 午夜精品99久久免费| 亚洲xxxx3d| 日本久久久a级免费| 91沈先生作品| 久久久久久有精品国产| 麻豆国产va免费精品高清在线| 国内精品视频一区| 欧美极品少妇xxxxⅹ免费视频| 国产成人精品电影| 欧美xxxx做受欧美.88| 日韩美女在线观看| 亚洲一区美女视频在线观看免费| 欧美日韩激情视频| 国产欧美va欧美va香蕉在| 久久国产精品久久精品| 亚洲bt天天射| 亚洲在线免费观看| 91久久久久久久| 精品欧美激情精品一区| 亚洲激情在线观看视频免费| 中文字幕日韩在线观看| 欧美一级视频一区二区| 欧美极品少妇xxxxⅹ裸体艺术| 亚洲午夜av久久乱码| 欧美日韩一区二区在线播放| 欧洲美女7788成人免费视频| 日韩中文字幕在线精品| 美乳少妇欧美精品| 亚洲一区二区三区777| 久久久亚洲欧洲日产国码aⅴ| 成人激情电影一区二区| 国内久久久精品| 精品国模在线视频| 亚洲综合大片69999| 色综合天天综合网国产成人网| 国产欧美一区二区三区在线看| 久久人人爽人人| 欧美日韩免费区域视频在线观看| 欧美重口另类videos人妖| 1769国内精品视频在线播放| 亚洲国产日韩欧美在线99| 久久免费国产视频| 精品久久久免费| 91亚洲国产成人精品性色| 蜜臀久久99精品久久久久久宅男| 91精品啪在线观看麻豆免费| 亚洲自拍偷拍福利| 亚洲国产精品999| 在线观看日韩视频| 91中文字幕一区| 久久久精品久久久久| 欧美午夜性色大片在线观看| 精品二区三区线观看| 亚洲黄在线观看| 中文字幕一精品亚洲无线一区| 日韩国产欧美精品在线| 亚洲乱码av中文一区二区| 国产亚洲综合久久| yw.139尤物在线精品视频| 欧美www视频在线观看| 亚洲男人av电影| 97在线视频免费| 黑人巨大精品欧美一区二区一视频| 激情亚洲一区二区三区四区| 这里只有视频精品| 国模精品视频一区二区三区| 国产精品无av码在线观看| 日韩精品黄色网| 好吊成人免视频| 精品视频偷偷看在线观看| 久久久久久av| 久久人人爽人人爽人人片av高清| 91香蕉嫩草影院入口| 51色欧美片视频在线观看| 国产午夜精品全部视频在线播放| 亚洲精品一区二区三区不| 91在线观看免费观看| 国产美女搞久久| 色婷婷综合成人| 久久国产色av| 日韩av在线导航| 国产精品自产拍在线观看中文| 久久久www成人免费精品张筱雨| 欧美性猛交xxxx免费看久久久| 中文字幕免费精品一区高清| 国产精品极品尤物在线观看| 日韩小视频网址| 精品视频9999| 国产精品亚洲片夜色在线| 欧美激情伊人电影| 日本伊人精品一区二区三区介绍| 国产精品一区二区三区在线播放| 久热在线中文字幕色999舞| 亚洲精品视频在线播放| 欧美在线免费视频| 国产精品视频中文字幕91| 亚洲午夜未删减在线观看| 亚洲欧美综合区自拍另类| 中文字幕欧美国内| 性夜试看影院91社区| 久久免费精品视频| 国产91精品在线播放| 一区二区三区高清国产| 国产视频亚洲视频| 国产精品夫妻激情| 欧美午夜激情小视频| 亚洲最新av网址| 日韩电影在线观看免费| 欧美精品久久久久久久| 日韩精品欧美国产精品忘忧草| 亚洲色图日韩av| 91久久精品美女| 久久av中文字幕| 2019亚洲日韩新视频| 国产+成+人+亚洲欧洲| 国产ts人妖一区二区三区| 亚洲国产精品人人爽夜夜爽| 91久久久在线| 欧美在线视频在线播放完整版免费观看| 日韩动漫免费观看电视剧高清| 97国产精品久久| 久热国产精品视频| 国产欧美一区二区三区久久人妖| 九九热精品视频| 97久久精品人人澡人人爽缅北| 国产成人精品久久二区二区| 欧美伊久线香蕉线新在线| 综合久久五月天| 成人亚洲综合色就1024| 日韩在线观看免费高清| 久久精品影视伊人网| 欧美成人第一页| 97成人精品视频在线观看| 久久综合九色九九| 亚洲高清一二三区| 欧美日韩国产区| 成人a在线视频| 欧美亚洲一级片| 成人精品在线视频| www.xxxx精品| 国产美女久久久| 亚洲天堂成人在线|