久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OkHttp实现分析之Websocket

發(fā)布時(shí)間:2024/4/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OkHttp实现分析之Websocket 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

HTML5 擁有許多引人注目的新特性,WebSocket就是其中之一。WebSocket一向有著 “Web 的 TCP ”之稱。通常 WebSocket 都是用于Web的,用于構(gòu)建實(shí)時(shí)的 Web 應(yīng)用。它可以在瀏覽器和服務(wù)器之間提供一個(gè)基于 TCP 連接的雙向通道。

WebSocket 協(xié)議本質(zhì)上是一個(gè)基于 TCP 的協(xié)議。為了建立一個(gè) WebSocket 連接,客戶端瀏覽器首先要向服務(wù)器發(fā)起一個(gè) HTTP 請(qǐng)求,這個(gè)請(qǐng)求和通常的 HTTP 請(qǐng)求不同,包含了一些附加頭信息,其中附加頭信息 ”Upgrade: WebSocket” 表明這是一個(gè)申請(qǐng)協(xié)議升級(jí)的 HTTP 請(qǐng)求,服務(wù)器端解析這些附加的頭信息然后產(chǎn)生應(yīng)答信息返回給客戶端,客戶端和服務(wù)器端的 WebSocket 連接就建立起來(lái)了,雙方就可以通過(guò)這個(gè)連接通道自由的傳遞信息,并且這個(gè)連接會(huì)持續(xù)存在直到客戶端或者服務(wù)器端的某一方主動(dòng)的關(guān)閉連接。

Websocket同樣可以用于移動(dòng)端。盡管移動(dòng)端 Android/iOS 的本地應(yīng)用可以直接通過(guò)Socket與服務(wù)器建立連接,并定義自己的協(xié)議來(lái)解決 Web 中實(shí)時(shí)應(yīng)用創(chuàng)建困難的問(wèn)題,但 WebSocket 服務(wù)通常復(fù)用Web的 80 端口,且可以比較方便的基于Web服務(wù)器來(lái)實(shí)現(xiàn),因而對(duì)于某些端口容易被封的網(wǎng)絡(luò)環(huán)境而言,WebSocket 就變得非常有意義。

OkHttp 是在 2016 年 6 月 10 日發(fā)布的 3.4.1 版中添加的對(duì)WebSocket的支持的。本文通過(guò)分析 OkHttp-3.5.0 的 WebSocket 實(shí)現(xiàn)來(lái)學(xué)習(xí)一下這個(gè)協(xié)議。

OkHttp WebSocket客戶端 API 用法

在開(kāi)始分析 WebSocket 的實(shí)現(xiàn)之前,我們先來(lái)看一下 OkHttp 的 WebSocket API怎么用。示例代碼如下:

import android.util.Log;import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString;public class WebsocketClient {private static final int NORMAL_CLOSURE_STATUS = 1000;private static OkHttpClient sClient;private static WebSocket sWebSocket;public static synchronized void startRequest() {if (sClient == null) {sClient = new OkHttpClient();}if (sWebSocket == null) {Request request = new Request.Builder().url("ws://echo.websocket.org").build();EchoWebSocketListener listener = new EchoWebSocketListener();sWebSocket = sClient.newWebSocket(request, listener);}}private static void sendMessage(WebSocket webSocket) {webSocket.send("Knock, knock!");webSocket.send("Hello!");webSocket.send(ByteString.decodeHex("deadbeef"));}public static void sendMessage() {WebSocket webSocket;synchronized (WebsocketClient.class) {webSocket = sWebSocket;}if (webSocket != null) {sendMessage(webSocket);}}public static synchronized void closeWebSocket() {if (sWebSocket != null) {sWebSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye!");sWebSocket = null;}}public static synchronized void destroy() {if (sClient != null) {sClient.dispatcher().executorService().shutdown();sClient = null;}}private static void resetWebSocket() {synchronized (WebsocketClient.class) {sWebSocket = null;}}public static class EchoWebSocketListener extends WebSocketListener {private static final String TAG = "EchoWebSocketListener";@Overridepublic void onOpen(WebSocket webSocket, Response response) {sendMessage(webSocket);}@Overridepublic void onMessage(WebSocket webSocket, String text) {Log.i(TAG, "Receiving: " + text);}@Overridepublic void onMessage(WebSocket webSocket, ByteString bytes) {Log.i(TAG, "Receiving: " + bytes.hex());}@Overridepublic void onClosing(WebSocket webSocket, int code, String reason) {webSocket.close(NORMAL_CLOSURE_STATUS, null);Log.i(TAG, "Closing: " + code + " " + reason);resetWebSocket();}@Overridepublic void onClosed(WebSocket webSocket, int code, String reason) {Log.i(TAG, "Closed: " + code + " " + reason);}@Overridepublic void onFailure(WebSocket webSocket, Throwable t, Response response) {t.printStackTrace();resetWebSocket();}} }

這個(gè)過(guò)程與發(fā)送HTTP請(qǐng)求的過(guò)程有許多相似之處,它們都需要?jiǎng)?chuàng)建 OkHttpClient 和Request。然而它們不同的地方更多:

  • WebSocket 請(qǐng)求通過(guò) WebSocketListener 來(lái)接收連接的狀態(tài)和活動(dòng),而HTTP請(qǐng)求則通過(guò) Callback。同時(shí)請(qǐng)求的 URL 的 scheme 是 “ws” 或者是 “wss” (TLS 之上的 WebSocket),而不是HTTP的 "http" 和 "https"。
  • HTTP 請(qǐng)求的連接建立及執(zhí)行需要基于 Request 和回調(diào)創(chuàng)建Call,并調(diào)用 Call 的方法手動(dòng)進(jìn)行;而對(duì)于 WebSocket 請(qǐng)求,則在基于 Request 和回調(diào)創(chuàng)建 WebSocket 的時(shí)候,OkHttp 會(huì)自動(dòng)發(fā)起連接建立的過(guò)程。
  • 這也是 WebSocket 與 HTTP 最大的不同。對(duì)于 WebSocket,我們可以保存 WebSocket 對(duì)象,并在后續(xù)多次通過(guò)該對(duì)象向服務(wù)器發(fā)送數(shù)據(jù)。
  • 通過(guò)回調(diào)可以獲得更多 WebSocket 的狀態(tài)變化。在連接建立、收到服務(wù)器發(fā)送回來(lái)的消息、服務(wù)器要關(guān)閉連接,以及出現(xiàn) error 時(shí),都能得到通知。不像 HTTP 請(qǐng)求那樣,只在最后得到一個(gè)請(qǐng)求成功或者失敗的結(jié)果。
  • 后兩點(diǎn)正是 WebSocket 全雙工連接的體現(xiàn)。

    OkHttp 的 WebSocket 實(shí)現(xiàn)

    接著我們來(lái)看OkHttp 的 WebSocket 實(shí)現(xiàn)。WebSocket 包含兩個(gè)部分,分別是握手和數(shù)據(jù)傳輸,數(shù)據(jù)傳輸又包括數(shù)據(jù)的發(fā)送,數(shù)據(jù)的接收,連接的保活,以及連接的關(guān)閉等,我們將分別分析這些過(guò)程。

    連接握手

    創(chuàng)建 WebSocket 的過(guò)程如下:

    public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {. . . . . .@Override public WebSocket newWebSocket(Request request, WebSocketListener listener) {RealWebSocket webSocket = new RealWebSocket(request, listener, new SecureRandom());webSocket.connect(this);return webSocket;}

    在這里會(huì)創(chuàng)建一個(gè) RealWebSocket 對(duì)象,然后執(zhí)行其 connect() 方法建立連接。 RealWebSocket 對(duì)象的創(chuàng)建過(guò)程如下:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .public RealWebSocket(Request request, WebSocketListener listener, Random random) {if (!"GET".equals(request.method())) {throw new IllegalArgumentException("Request must be GET: " + request.method());}this.originalRequest = request;this.listener = listener;this.random = random;byte[] nonce = new byte[16];random.nextBytes(nonce);this.key = ByteString.of(nonce).base64();this.writerRunnable = new Runnable() {@Override public void run() {try {while (writeOneFrame()) {}} catch (IOException e) {failWebSocket(e, null);}}};}

    這里最主要的是初始化了 key,以備后續(xù)連接建立及握手之用。Key 是一個(gè)16字節(jié)長(zhǎng)的隨機(jī)數(shù)經(jīng)過(guò) Base64 編碼得到的。此外還初始化了 writerRunnable 等。

    連接建立及握手過(guò)程如下:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .public void connect(OkHttpClient client) {client = client.newBuilder().protocols(ONLY_HTTP1).build();final int pingIntervalMillis = client.pingIntervalMillis();final Request request = originalRequest.newBuilder().header("Upgrade", "websocket").header("Connection", "Upgrade").header("Sec-WebSocket-Key", key).header("Sec-WebSocket-Version", "13").build();call = Internal.instance.newWebSocketCall(client, request);call.enqueue(new Callback() {@Override public void onResponse(Call call, Response response) {try {checkResponse(response);} catch (ProtocolException e) {failWebSocket(e, response);closeQuietly(response);return;}// Promote the HTTP streams into web socket streams.StreamAllocation streamAllocation = Internal.instance.streamAllocation(call);streamAllocation.noNewStreams(); // Prevent connection pooling!Streams streams = streamAllocation.connection().newWebSocketStreams(streamAllocation);// Process all web socket messages.try {listener.onOpen(RealWebSocket.this, response);String name = "OkHttp WebSocket " + request.url().redact();initReaderAndWriter(name, pingIntervalMillis, streams);streamAllocation.connection().socket().setSoTimeout(0);loopReader();} catch (Exception e) {failWebSocket(e, null);}}@Override public void onFailure(Call call, IOException e) {failWebSocket(e, null);}});}

    連接建立及握手的過(guò)程主要是向服務(wù)器發(fā)送一個(gè)HTTP請(qǐng)求。這個(gè) HTTP 請(qǐng)求的特別之處在于,它包含了如下的一些Headers:

    Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Key: 7wgaspE0Tl7/66o4Dov2kw== Sec-WebSocket-Version: 13

    其中 Upgrade 和 Connection header 向服務(wù)器表明,請(qǐng)求的目的就是要將客戶端和服務(wù)器端的通訊協(xié)議從 HTTP 協(xié)議升級(jí)到 WebSocket 協(xié)議,同時(shí)在請(qǐng)求處理完成之后,連接不要斷開(kāi)。Sec-WebSocket-Key header 值正是我們前面看到的key,它是 WebSocket 客戶端發(fā)送的一個(gè) base64 編碼的密文,要求服務(wù)端必須返回一個(gè)對(duì)應(yīng)加密的 “Sec-WebSocket-Accept” 應(yīng)答,否則客戶端會(huì)拋出 “Error during WebSocket handshake” 錯(cuò)誤,并關(guān)閉連接。

    來(lái)自于 HTTP 服務(wù)器的響應(yīng)到達(dá)的時(shí)候,即是連接建立大功告成的時(shí)候,也就是熱豆腐孰了的時(shí)候。

    然而,響應(yīng)到達(dá)時(shí),盡管連接已經(jīng)建立,還要為數(shù)據(jù)的收發(fā)做一些準(zhǔn)備。這些準(zhǔn)備中的第一步就是檢查 HTTP 響應(yīng):

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .void checkResponse(Response response) throws ProtocolException {if (response.code() != 101) {throw new ProtocolException("Expected HTTP 101 response but was '"+ response.code() + " " + response.message() + "'");}String headerConnection = response.header("Connection");if (!"Upgrade".equalsIgnoreCase(headerConnection)) {throw new ProtocolException("Expected 'Connection' header value 'Upgrade' but was '"+ headerConnection + "'");}String headerUpgrade = response.header("Upgrade");if (!"websocket".equalsIgnoreCase(headerUpgrade)) {throw new ProtocolException("Expected 'Upgrade' header value 'websocket' but was '" + headerUpgrade + "'");}String headerAccept = response.header("Sec-WebSocket-Accept");String acceptExpected = ByteString.encodeUtf8(key + WebSocketProtocol.ACCEPT_MAGIC).sha1().base64();if (!acceptExpected.equals(headerAccept)) {throw new ProtocolException("Expected 'Sec-WebSocket-Accept' header value '"+ acceptExpected + "' but was '" + headerAccept + "'");}}. . . . . .public void failWebSocket(Exception e, Response response) {Streams streamsToClose;synchronized (this) {if (failed) return; // Already failed.failed = true;streamsToClose = this.streams;this.streams = null;if (cancelFuture != null) cancelFuture.cancel(false);if (executor != null) executor.shutdown();}try {listener.onFailure(this, e, response);} finally {closeQuietly(streamsToClose);}}

    根據(jù) WebSocket 的協(xié)議,服務(wù)器端用如下響應(yīng),來(lái)表示接受建立 WebSocket 連接的請(qǐng)求:

  • 響應(yīng)碼是 101。
  • "Connection" header 的值為 "Upgrade",以表明服務(wù)器并沒(méi)有在處理完請(qǐng)求之后把連接個(gè)斷開(kāi)。
  • "Upgrade" header 的值為 "websocket",以表明服務(wù)器接受后面使用 WebSocket 來(lái)通信。
  • "Sec-WebSocket-Accept" header 的值為,key + WebSocketProtocol.ACCEPT_MAGIC 做 SHA1 hash,然后做 base64 編碼,來(lái)做服務(wù)器接受連接的驗(yàn)證。關(guān)于這部分的設(shè)計(jì)的詳細(xì)信息,可參考 WebSocket 協(xié)議規(guī)范。
  • 為數(shù)據(jù)收發(fā)做準(zhǔn)備的第二步是,初始化用于輸入輸出的 Source 和 Sink。Source 和 Sink 創(chuàng)建于之前發(fā)送HTTP請(qǐng)求的時(shí)候。這里會(huì)阻止在這個(gè)連接上再創(chuàng)建新的流。

    public final class RealConnection extends Http2Connection.Listener implements Connection {. . . . . .public RealWebSocket.Streams newWebSocketStreams(final StreamAllocation streamAllocation) {return new RealWebSocket.Streams(true, source, sink) {@Override public void close() throws IOException {streamAllocation.streamFinished(true, streamAllocation.codec());}};}

    Streams是一個(gè) BufferedSource 和 BufferedSink 的holder:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .public abstract static class Streams implements Closeable {public final boolean client;public final BufferedSource source;public final BufferedSink sink;public Streams(boolean client, BufferedSource source, BufferedSink sink) {this.client = client;this.source = source;this.sink = sink;}}

    第三步是調(diào)用回調(diào) onOpen()。

    第四步是初始化 Reader 和 Writer:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .public void initReaderAndWriter(String name, long pingIntervalMillis, Streams streams) throws IOException {synchronized (this) {this.streams = streams;this.writer = new WebSocketWriter(streams.client, streams.sink, random);this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false));if (pingIntervalMillis != 0) {executor.scheduleAtFixedRate(new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS);}if (!messageAndCloseQueue.isEmpty()) {runWriter(); // Send messages that were enqueued before we were connected.}}reader = new WebSocketReader(streams.client, streams.source, this);}

    OkHttp使用 WebSocketReader 和 WebSocketWriter 來(lái)處理數(shù)據(jù)的收發(fā)。在發(fā)送數(shù)據(jù)時(shí)將數(shù)據(jù)組織成幀,在接收數(shù)據(jù)時(shí)則進(jìn)行反向擦做,同時(shí)處理 WebSocket 的控制消息。

    WebSocket 的所有數(shù)據(jù)發(fā)送動(dòng)作,都會(huì)在單線程線程池的線程中,通過(guò) WebSocketWriter 執(zhí)行。在這里會(huì)創(chuàng)建 ScheduledThreadPoolExecutor 用于跑數(shù)據(jù)的發(fā)送操作。WebSocket 協(xié)議中主要會(huì)傳輸兩種類型的幀,一是控制幀,主要是用于連接保活的 Ping 幀等;二是用戶數(shù)據(jù)載荷幀。在這里會(huì)根據(jù)用戶的配置,調(diào)度 Ping 幀周期性地發(fā)送。我們?cè)谡{(diào)用 WebSocket 的接口發(fā)送數(shù)據(jù)時(shí),數(shù)據(jù)并不是同步發(fā)送的,而是被放在了一個(gè)消息隊(duì)列中。發(fā)送消息的 Runnable 從消息隊(duì)列中讀取數(shù)據(jù)發(fā)送。這里會(huì)檢查消息隊(duì)列中是否有數(shù)據(jù),如果有的話,會(huì)調(diào)度發(fā)送消息的 Runnable 執(zhí)行。

    第五步是配置socket的超時(shí)時(shí)間為0,也就是阻塞IO。

    第六步執(zhí)行 loopReader()。這實(shí)際上是進(jìn)入了消息讀取循環(huán)了,也就是數(shù)據(jù)接收的邏輯了。

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

    我們可以通過(guò) WebSocket 接口的 send(String text) 和 send(ByteString bytes) 分別發(fā)送文本的和二進(jìn)制格式的消息。

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .@Override public boolean send(String text) {if (text == null) throw new NullPointerException("text == null");return send(ByteString.encodeUtf8(text), OPCODE_TEXT);}@Override public boolean send(ByteString bytes) {if (bytes == null) throw new NullPointerException("bytes == null");return send(bytes, OPCODE_BINARY);}private synchronized boolean send(ByteString data, int formatOpcode) {// Don't send new frames after we've failed or enqueued a close frame.if (failed || enqueuedClose) return false;// If this frame overflows the buffer, reject it and close the web socket.if (queueSize + data.size() > MAX_QUEUE_SIZE) {close(CLOSE_CLIENT_GOING_AWAY, null);return false;}// Enqueue the message frame.queueSize += data.size();messageAndCloseQueue.add(new Message(formatOpcode, data));runWriter();return true;}. . . . . .private void runWriter() {assert (Thread.holdsLock(this));if (executor != null) {executor.execute(writerRunnable);}}

    可以看到我們調(diào)用發(fā)送數(shù)據(jù)的接口時(shí),做的事情主要是將數(shù)據(jù)格式化,構(gòu)造消息,放進(jìn)一個(gè)消息隊(duì)列,然后調(diào)度 writerRunnable 執(zhí)行。

    此外,值得注意的是,當(dāng)消息隊(duì)列中的未發(fā)送數(shù)據(jù)超出最大大小限制,WebSocket 連接會(huì)被直接關(guān)閉。對(duì)于發(fā)送失敗過(guò)或被關(guān)閉了的 WebSocket,將無(wú)法再發(fā)送信息。

    在 writerRunnable 中會(huì)循環(huán)調(diào)用 writeOneFrame() 逐幀發(fā)送數(shù)據(jù),直到數(shù)據(jù)發(fā)完,或發(fā)送失敗。在 WebSocket 協(xié)議中,客戶端需要發(fā)送 四種類型 的幀:

  • PING 幀
  • PONG 幀
  • CLOSE 幀
  • MESSAGE 幀
  • PING幀用于連接保活,它的發(fā)送是在 PingRunnable 中執(zhí)行的,在初始化 Reader 和 Writer 的時(shí)候,就會(huì)根據(jù)設(shè)置調(diào)度執(zhí)行或不執(zhí)行。除PING 幀外的其它 三種 幀,都在 writeOneFrame() 中發(fā)送。PONG 幀是對(duì)服務(wù)器發(fā)過(guò)來(lái)的 PING 幀的響應(yīng),同樣用于保活連接。后面我們?cè)诜治鲞B接的保活時(shí)會(huì)更詳細(xì)的分析 PING 和 PONG 這兩種幀。CLOSE 幀用于關(guān)閉連接,稍后我們?cè)诜治鲞B接關(guān)閉過(guò)程時(shí)再來(lái)詳細(xì)地分析。

    這里我們主要關(guān)注用戶數(shù)據(jù)發(fā)送的部分。PONG 幀具有最高的發(fā)送優(yōu)先級(jí)。在沒(méi)有PONG 幀需要發(fā)送時(shí),writeOneFrame() 從消息隊(duì)列中取出一條消息,如果消息不是 CLOSE 幀,則主要通過(guò)如下的過(guò)程進(jìn)行發(fā)送:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .boolean writeOneFrame() throws IOException {WebSocketWriter writer;ByteString pong;Object messageOrClose = null;int receivedCloseCode = -1;String receivedCloseReason = null;Streams streamsToClose = null;synchronized (RealWebSocket.this) {if (failed) {return false; // Failed web socket.}writer = this.writer;pong = pongQueue.poll();if (pong == null) {messageOrClose = messageAndCloseQueue.poll();. . . . . .} else if (messageOrClose instanceof Message) {ByteString data = ((Message) messageOrClose).data;BufferedSink sink = Okio.buffer(writer.newMessageSink(((Message) messageOrClose).formatOpcode, data.size()));sink.write(data);sink.close();synchronized (this) {queueSize -= data.size();}} else if (messageOrClose instanceof Close) {

    數(shù)據(jù)發(fā)送的過(guò)程可以總結(jié)如下:

  • 創(chuàng)建一個(gè) BufferedSink 用于數(shù)據(jù)發(fā)送。
  • 將數(shù)據(jù)寫入前面創(chuàng)建的 BufferedSink 中。
  • 關(guān)閉 BufferedSink。
  • 更新 queueSize 以正確地指示未發(fā)送數(shù)據(jù)的長(zhǎng)度。
  • 這里面的玄機(jī)主要在創(chuàng)建的 BufferedSink。創(chuàng)建的 Sink 是一個(gè) FrameSink:

    static void toggleMask(byte[] buffer, long byteCount, byte[] key, long frameBytesRead) {int keyLength = key.length;for (int i = 0; i < byteCount; i++, frameBytesRead++) {int keyIndex = (int) (frameBytesRead % keyLength);buffer[i] = (byte) (buffer[i] ^ key[keyIndex]);}}. . . . . .Sink newMessageSink(int formatOpcode, long contentLength) {if (activeWriter) {throw new IllegalStateException("Another message writer is active. Did you call close()?");}activeWriter = true;// Reset FrameSink state for a new writer.frameSink.formatOpcode = formatOpcode;frameSink.contentLength = contentLength;frameSink.isFirstFrame = true;frameSink.closed = false;return frameSink;}void writeMessageFrameSynchronized(int formatOpcode, long byteCount, boolean isFirstFrame,boolean isFinal) throws IOException {assert Thread.holdsLock(this);if (writerClosed) throw new IOException("closed");int b0 = isFirstFrame ? formatOpcode : OPCODE_CONTINUATION;if (isFinal) {b0 |= B0_FLAG_FIN;}sink.writeByte(b0);int b1 = 0;if (isClient) {b1 |= B1_FLAG_MASK;}if (byteCount <= PAYLOAD_BYTE_MAX) {b1 |= (int) byteCount;sink.writeByte(b1);} else if (byteCount <= PAYLOAD_SHORT_MAX) {b1 |= PAYLOAD_SHORT;sink.writeByte(b1);sink.writeShort((int) byteCount);} else {b1 |= PAYLOAD_LONG;sink.writeByte(b1);sink.writeLong(byteCount);}if (isClient) {random.nextBytes(maskKey);sink.write(maskKey);for (long written = 0; written < byteCount; ) {int toRead = (int) Math.min(byteCount, maskBuffer.length);int read = buffer.read(maskBuffer, 0, toRead);if (read == -1) throw new AssertionError();toggleMask(maskBuffer, read, maskKey, written);sink.write(maskBuffer, 0, read);written += read;}} else {sink.write(buffer, byteCount);}sink.emit();}final class FrameSink implements Sink {int formatOpcode;long contentLength;boolean isFirstFrame;boolean closed;@Override public void write(Buffer source, long byteCount) throws IOException {if (closed) throw new IOException("closed");buffer.write(source, byteCount);// Determine if this is a buffered write which we can defer until close() flushes.boolean deferWrite = isFirstFrame&& contentLength != -1&& buffer.size() > contentLength - 8192 /* segment size */;long emitCount = buffer.completeSegmentByteCount();if (emitCount > 0 && !deferWrite) {synchronized (WebSocketWriter.this) {writeMessageFrameSynchronized(formatOpcode, emitCount, isFirstFrame, false /* final */);}isFirstFrame = false;}}@Override public void flush() throws IOException {if (closed) throw new IOException("closed");synchronized (WebSocketWriter.this) {writeMessageFrameSynchronized(formatOpcode, buffer.size(), isFirstFrame, false /* final */);}isFirstFrame = false;}@Override public Timeout timeout() {return sink.timeout();}@SuppressWarnings("PointlessBitwiseExpression")@Override public void close() throws IOException {if (closed) throw new IOException("closed");synchronized (WebSocketWriter.this) {writeMessageFrameSynchronized(formatOpcode, buffer.size(), isFirstFrame, true /* final */);}closed = true;activeWriter = false;}}

    FrameSink 的 write() 會(huì)先將數(shù)據(jù)寫如一個(gè) Buffer 中,然后再?gòu)倪@個(gè) Buffer 中讀取數(shù)據(jù)來(lái)發(fā)送。如果是第一次發(fā)送數(shù)據(jù),同時(shí)剩余要發(fā)送的數(shù)據(jù)小于 8192 字節(jié)時(shí),會(huì)延遲執(zhí)行實(shí)際的數(shù)據(jù)發(fā)送,等 close() 時(shí)刷新。根據(jù) RealWebSocket 的 writeOneFrame() 的邏輯,在 write() 時(shí),總是寫入整個(gè)消息的所有數(shù)據(jù),因而,在 FrameSink 的 write() 中總是不會(huì)發(fā)送數(shù)據(jù)的。

    writeMessageFrameSynchronized() 將用戶數(shù)據(jù)格式化并發(fā)送出去。規(guī)范中定義的數(shù)據(jù)格式如下:

    0 1 2 30 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+-+-+-+-+-------+-+-------------+-------------------------------+|F|R|R|R| opcode|M| Payload len | Extended payload length ||I|S|S|S| (4) |A| (7) | (16/64) ||N|V|V|V| |S| | (if payload len==126/127) || |1|2|3| |K| | |+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +| Extended payload length continued, if payload len == 127 |+ - - - - - - - - - - - - - - - +-------------------------------+| |Masking-key, if MASK set to 1 |+-------------------------------+-------------------------------+| Masking-key (continued) | Payload Data |+-------------------------------- - - - - - - - - - - - - - - - +: Payload Data continued ... :+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +| Payload Data continued ... |+---------------------------------------------------------------+

    基本結(jié)構(gòu)為:

  • 第一個(gè)字節(jié)是 meta data 控制位,包括四位的操作碼,用于指明這是否是消息的最后一幀的FIN位及三個(gè)保留位。
  • 第二個(gè)字節(jié)包括掩碼位,和載荷長(zhǎng)度或載荷長(zhǎng)度指示。只有載荷長(zhǎng)度比較小,在 127 以內(nèi)時(shí),載荷長(zhǎng)度才會(huì)包含在這個(gè)字節(jié)中。否則這個(gè)字節(jié)中將包含載荷長(zhǎng)度指示的位。
  • 可選的載荷長(zhǎng)度。載荷長(zhǎng)度大于127時(shí),幀中會(huì)專門有一些字節(jié)來(lái)描述載荷的長(zhǎng)度。載荷長(zhǎng)度具體占用幾個(gè)自己,因載荷的實(shí)際長(zhǎng)度而異。
  • 可選的掩碼字節(jié)。客戶端發(fā)送的幀,設(shè)置掩碼指示位,并包含四個(gè)字節(jié)的掩碼字節(jié)。
  • 載荷數(shù)據(jù)。客戶端發(fā)送的數(shù)據(jù),會(huì)將原始的數(shù)據(jù)與掩碼字節(jié)做異或之后再發(fā)送。
  • 關(guān)于幀格式的更詳細(xì)信息,可以參考 WebSocket Protocol 規(guī)范。

    數(shù)據(jù)的接收

    如我們前面看到的, 在握手的HTTP請(qǐng)求返回之后,會(huì)在HTTP請(qǐng)求的回調(diào)里,啟動(dòng)消息讀取循環(huán) loopReader():

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . ./** Receive frames until there are no more. Invoked only by the reader thread. */public void loopReader() throws IOException {while (receivedCloseCode == -1) {// This method call results in one or more onRead* methods being called on this thread.reader.processNextFrame();}}

    在這個(gè)循環(huán)中,不斷通過(guò) WebSocketReader 的 processNextFrame() 讀取消息,直到收到了關(guān)閉連接的消息。

    final class WebSocketReader {public interface FrameCallback {void onReadMessage(String text) throws IOException;void onReadMessage(ByteString bytes) throws IOException;void onReadPing(ByteString buffer);void onReadPong(ByteString buffer);void onReadClose(int code, String reason);}. . . . . .void processNextFrame() throws IOException {readHeader();if (isControlFrame) {readControlFrame();} else {readMessageFrame();}}private void readHeader() throws IOException {if (closed) throw new IOException("closed");// Disable the timeout to read the first byte of a new frame.int b0;long timeoutBefore = source.timeout().timeoutNanos();source.timeout().clearTimeout();try {b0 = source.readByte() & 0xff;} finally {source.timeout().timeout(timeoutBefore, TimeUnit.NANOSECONDS);}opcode = b0 & B0_MASK_OPCODE;isFinalFrame = (b0 & B0_FLAG_FIN) != 0;isControlFrame = (b0 & OPCODE_FLAG_CONTROL) != 0;// Control frames must be final frames (cannot contain continuations).if (isControlFrame && !isFinalFrame) {throw new ProtocolException("Control frames must be final.");}boolean reservedFlag1 = (b0 & B0_FLAG_RSV1) != 0;boolean reservedFlag2 = (b0 & B0_FLAG_RSV2) != 0;boolean reservedFlag3 = (b0 & B0_FLAG_RSV3) != 0;if (reservedFlag1 || reservedFlag2 || reservedFlag3) {// Reserved flags are for extensions which we currently do not support.throw new ProtocolException("Reserved flags are unsupported.");}int b1 = source.readByte() & 0xff;isMasked = (b1 & B1_FLAG_MASK) != 0;if (isMasked == isClient) {// Masked payloads must be read on the server. Unmasked payloads must be read on the client.throw new ProtocolException(isClient? "Server-sent frames must not be masked.": "Client-sent frames must be masked.");}// Get frame length, optionally reading from follow-up bytes if indicated by special values.frameLength = b1 & B1_MASK_LENGTH;if (frameLength == PAYLOAD_SHORT) {frameLength = source.readShort() & 0xffffL; // Value is unsigned.} else if (frameLength == PAYLOAD_LONG) {frameLength = source.readLong();if (frameLength < 0) {throw new ProtocolException("Frame length 0x" + Long.toHexString(frameLength) + " > 0x7FFFFFFFFFFFFFFF");}}frameBytesRead = 0;if (isControlFrame && frameLength > PAYLOAD_BYTE_MAX) {throw new ProtocolException("Control frame must be less than " + PAYLOAD_BYTE_MAX + "B.");}if (isMasked) {// Read the masking key as bytes so that they can be used directly for unmasking.source.readFully(maskKey);}}

    processNextFrame() 先讀取 Header 的兩個(gè)字節(jié),然后根據(jù) Header 的信息,讀取數(shù)據(jù)內(nèi)容。

    在讀取 Header 時(shí),讀的第一個(gè)字節(jié)是同步的不計(jì)超時(shí)時(shí)間的。WebSocketReader 從 Header 中,獲取到這個(gè)幀是不是消息的最后一幀,消息的類型,是否有掩碼字節(jié),保留位,幀的長(zhǎng)度,以及掩碼字節(jié)等信息。WebSocket 通過(guò)掩碼位和掩碼字節(jié)來(lái)區(qū)分?jǐn)?shù)據(jù)是從客戶端發(fā)送給服務(wù)器的,還是服務(wù)器發(fā)送給客戶端的。這里會(huì)根據(jù)協(xié)議,對(duì)這些信息進(jìn)行有效性一致性檢驗(yàn),若不一致則會(huì)拋出 ProtocolException。

    WebSocketReader 同步讀取時(shí)的調(diào)用棧如下:


    Reader Thread

    通過(guò)幀的 Header 確定了是數(shù)據(jù)幀,則會(huì)執(zhí)行 readMessageFrame() 讀取消息幀:

    final class WebSocketReader {. . . . . .private void readMessageFrame() throws IOException {int opcode = this.opcode;if (opcode != OPCODE_TEXT && opcode != OPCODE_BINARY) {throw new ProtocolException("Unknown opcode: " + toHexString(opcode));}Buffer message = new Buffer();readMessage(message);if (opcode == OPCODE_TEXT) {frameCallback.onReadMessage(message.readUtf8());} else {frameCallback.onReadMessage(message.readByteString());}}/** Read headers and process any control frames until we reach a non-control frame. */void readUntilNonControlFrame() throws IOException {while (!closed) {readHeader();if (!isControlFrame) {break;}readControlFrame();}}/*** Reads a message body into across one or more frames. Control frames that occur between* fragments will be processed. If the message payload is masked this will unmask as it's being* processed.*/private void readMessage(Buffer sink) throws IOException {while (true) {if (closed) throw new IOException("closed");if (frameBytesRead == frameLength) {if (isFinalFrame) return; // We are exhausted and have no continuations.readUntilNonControlFrame();if (opcode != OPCODE_CONTINUATION) {throw new ProtocolException("Expected continuation opcode. Got: " + toHexString(opcode));}if (isFinalFrame && frameLength == 0) {return; // Fast-path for empty final frame.}}long toRead = frameLength - frameBytesRead;long read;if (isMasked) {toRead = Math.min(toRead, maskBuffer.length);read = source.read(maskBuffer, 0, (int) toRead);if (read == -1) throw new EOFException();toggleMask(maskBuffer, read, maskKey, frameBytesRead);sink.write(maskBuffer, 0, (int) read);} else {read = source.read(sink, toRead);if (read == -1) throw new EOFException();}frameBytesRead += read;}}

    這個(gè)過(guò)程中,會(huì)讀取一條消息包含的所有數(shù)據(jù)幀。按照 WebSocket 的標(biāo)準(zhǔn),包含用戶數(shù)據(jù)的消息數(shù)據(jù)幀可以和控制幀交替發(fā)送;但消息之間的數(shù)據(jù)幀不可以。因而在這個(gè)過(guò)程中,若遇到了控制幀,則會(huì)先讀取控制幀進(jìn)行處理,然后繼續(xù)讀取消息的數(shù)據(jù)幀,直到讀取了消息的所有數(shù)據(jù)幀。

    掩碼位和掩碼字節(jié),對(duì)于客戶端而言,發(fā)送的數(shù)據(jù)中包含這些東西,在接收的數(shù)據(jù)中不包含這些;對(duì)于服務(wù)器而言,則是在接收的數(shù)據(jù)中包含這些,發(fā)送的數(shù)據(jù)中不包含。OkHttp 既支持服務(wù)器開(kāi)發(fā),也支持客戶端開(kāi)發(fā),因而可以看到對(duì)于掩碼位和掩碼字節(jié)完整的處理。

    在一個(gè)消息讀取完成之后,會(huì)通過(guò)回調(diào) FrameCallback 將讀取的內(nèi)容通知出去。

    final class WebSocketReader {. . . . . .WebSocketReader(boolean isClient, BufferedSource source, FrameCallback frameCallback) {if (source == null) throw new NullPointerException("source == null");if (frameCallback == null) throw new NullPointerException("frameCallback == null");this.isClient = isClient;this.source = source;this.frameCallback = frameCallback;}

    這一事件會(huì)通知到 RealWebSocket。

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .@Override public void onReadMessage(String text) throws IOException {listener.onMessage(this, text);}@Override public void onReadMessage(ByteString bytes) throws IOException {listener.onMessage(this, bytes);}

    在 RealWebSocket 中,這一事件又被通知到我們?cè)趹?yīng)用程序中創(chuàng)建的回調(diào) WebSocketListener。

    連接的保活

    連接的保活通過(guò) PING 幀和 PONG 幀來(lái)實(shí)現(xiàn)。如我們前面看到的,若用戶設(shè)置了 PING 幀的發(fā)送周期,在握手的HTTP請(qǐng)求返回時(shí),消息讀取循環(huán)開(kāi)始前會(huì)調(diào)度 PingRunnable 周期性的向服務(wù)器發(fā)送 PING 幀:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .private final class PingRunnable implements Runnable {PingRunnable() {}@Override public void run() {writePingFrame();}}void writePingFrame() {WebSocketWriter writer;synchronized (this) {if (failed) return;writer = this.writer;}try {writer.writePing(ByteString.EMPTY);} catch (IOException e) {failWebSocket(e, null);}}

    在 PingRunnable 中,通過(guò) WebSocketWriter 發(fā)送 PING 幀:

    final class WebSocketWriter {. . . . . ./** Send a ping with the supplied {@code payload}. */void writePing(ByteString payload) throws IOException {synchronized (this) {writeControlFrameSynchronized(OPCODE_CONTROL_PING, payload);}}. . . . . .private void writeControlFrameSynchronized(int opcode, ByteString payload) throws IOException {assert Thread.holdsLock(this);if (writerClosed) throw new IOException("closed");int length = payload.size();if (length > PAYLOAD_BYTE_MAX) {throw new IllegalArgumentException("Payload size must be less than or equal to " + PAYLOAD_BYTE_MAX);}int b0 = B0_FLAG_FIN | opcode;sink.writeByte(b0);int b1 = length;if (isClient) {b1 |= B1_FLAG_MASK;sink.writeByte(b1);random.nextBytes(maskKey);sink.write(maskKey);byte[] bytes = payload.toByteArray();toggleMask(bytes, bytes.length, maskKey, 0);sink.write(bytes);} else {sink.writeByte(b1);sink.write(payload);}sink.flush();}

    PING 幀是一個(gè)不包含載荷的控制幀。關(guān)于掩碼位和掩碼字節(jié)的設(shè)置,與消息的數(shù)據(jù)幀相同。即客戶端發(fā)送的幀,設(shè)置掩碼位,幀中包含掩碼字節(jié);服務(wù)器發(fā)送的幀,不設(shè)置掩碼位,幀中不包含掩碼字節(jié)。

    通過(guò) WebSocket 通信的雙方,在收到對(duì)方發(fā)來(lái)的 PING 幀時(shí),需要用PONG幀來(lái)回復(fù)。在 WebSocketReader 的 readControlFrame() 中可以看到這一點(diǎn):

    final class WebSocketReader {. . . . . .private void readControlFrame() throws IOException {Buffer buffer = new Buffer();if (frameBytesRead < frameLength) {if (isClient) {source.readFully(buffer, frameLength);} else {while (frameBytesRead < frameLength) {int toRead = (int) Math.min(frameLength - frameBytesRead, maskBuffer.length);int read = source.read(maskBuffer, 0, toRead);if (read == -1) throw new EOFException();toggleMask(maskBuffer, read, maskKey, frameBytesRead);buffer.write(maskBuffer, 0, read);frameBytesRead += read;}}}switch (opcode) {case OPCODE_CONTROL_PING:frameCallback.onReadPing(buffer.readByteString());break;case OPCODE_CONTROL_PONG:frameCallback.onReadPong(buffer.readByteString());break;

    PING 幀和 PONG 幀都不帶載荷,控制幀讀寫時(shí)對(duì)于載荷長(zhǎng)度的處理,都是為 CLOSE 幀做的。因而針對(duì) PING 幀和 PONG 幀,除了 Header 外, readControlFrame() 實(shí)際上無(wú)需再讀取任何數(shù)據(jù),但它會(huì)將這些事件通知出去:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .@Override public synchronized void onReadPing(ByteString payload) {// Don't respond to pings after we've failed or sent the close frame.if (failed || (enqueuedClose && messageAndCloseQueue.isEmpty())) return;pongQueue.add(payload);runWriter();pingCount++;}@Override public synchronized void onReadPong(ByteString buffer) {// This API doesn't expose pings.pongCount++;}

    可見(jiàn)在收到 PING 幀的時(shí)候,總是會(huì)發(fā)一個(gè) PONG 幀出去,且通常其沒(méi)有載荷數(shù)據(jù)。在收到一個(gè) PONG 幀時(shí),則通常只是記錄一下,然后什么也不做。如我們前面所見(jiàn),PONG 幀在 writerRunnable 中被發(fā)送出去:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .if (pong != null) {writer.writePong(pong);} else if (messageOrClose instanceof Message) {

    PONG 幀的發(fā)送與 PING 幀的非常相似:

    final class WebSocketWriter {. . . . . ./** Send a pong with the supplied {@code payload}. */void writePong(ByteString payload) throws IOException {synchronized (this) {writeControlFrameSynchronized(OPCODE_CONTROL_PONG, payload);}}

    連接的關(guān)閉

    連接的關(guān)閉,與數(shù)據(jù)發(fā)送的過(guò)程頗有幾分相似之處。通過(guò) WebSocket 接口的 close(int code, String reason) 我們可以關(guān)閉一個(gè) WebSocket 連接:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .@Override public boolean close(int code, String reason) {return close(code, reason, CANCEL_AFTER_CLOSE_MILLIS);}synchronized boolean close(int code, String reason, long cancelAfterCloseMillis) {validateCloseCode(code);ByteString reasonBytes = null;if (reason != null) {reasonBytes = ByteString.encodeUtf8(reason);if (reasonBytes.size() > CLOSE_MESSAGE_MAX) {throw new IllegalArgumentException("reason.size() > " + CLOSE_MESSAGE_MAX + ": " + reason);}}if (failed || enqueuedClose) return false;// Immediately prevent further frames from being enqueued.enqueuedClose = true;// Enqueue the close frame.messageAndCloseQueue.add(new Close(code, reasonBytes, cancelAfterCloseMillis));runWriter();return true;}

    在執(zhí)行關(guān)閉連接動(dòng)作前,會(huì)先檢查一下 close code 的有效性在合法范圍內(nèi)。關(guān)于不同 close code 的詳細(xì)說(shuō)明,可以參考 WebSocket 協(xié)議規(guī)范。

    檢查完了之后,會(huì)構(gòu)造一個(gè) Close 消息放入發(fā)送消息隊(duì)列,并調(diào)度 writerRunnable 執(zhí)行。Close 消息可以帶有不超出 123 字節(jié)的字符串,以作為 Close message,來(lái)說(shuō)明連接關(guān)閉的原因。

    連接的關(guān)閉分為主動(dòng)關(guān)閉和被動(dòng)關(guān)閉。客戶端先向服務(wù)器發(fā)送一個(gè) CLOSE 幀,然后服務(wù)器恢復(fù)一個(gè) CLOSE 幀,對(duì)于客戶端而言,這個(gè)過(guò)程為主動(dòng)關(guān)閉;反之則為對(duì)客戶端而言則為被動(dòng)關(guān)閉。

    在 writerRunnable 執(zhí)行的 writeOneFrame() 實(shí)際發(fā)送 CLOSE 幀:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .messageOrClose = messageAndCloseQueue.poll();if (messageOrClose instanceof Close) {receivedCloseCode = this.receivedCloseCode;receivedCloseReason = this.receivedCloseReason;if (receivedCloseCode != -1) {streamsToClose = this.streams;this.streams = null;this.executor.shutdown();} else {// When we request a graceful close also schedule a cancel of the websocket.cancelFuture = executor.schedule(new CancelRunnable(),((Close) messageOrClose).cancelAfterCloseMillis, MILLISECONDS);}} else if (messageOrClose == null) {return false; // The queue is exhausted.}}. . . . . .} else if (messageOrClose instanceof Close) {Close close = (Close) messageOrClose;writer.writeClose(close.code, close.reason);// We closed the writer: now both reader and writer are closed.if (streamsToClose != null) {listener.onClosed(this, receivedCloseCode, receivedCloseReason);}} else {

    發(fā)送 CLOSE 幀也分為主動(dòng)關(guān)閉的發(fā)送還是被動(dòng)關(guān)閉的發(fā)送。
    對(duì)于被動(dòng)關(guān)閉,在發(fā)送完 CLOSE 幀之后,連接被最終關(guān)閉,因而,發(fā)送 CLOSE 幀之前,這里會(huì)停掉發(fā)送消息用的 executor。而在發(fā)送之后,則會(huì)通過(guò) onClosed() 通知用戶。

    而對(duì)于主動(dòng)關(guān)閉,則在發(fā)送前會(huì)調(diào)度 CancelRunnable 的執(zhí)行,發(fā)送后不會(huì)通過(guò) onClosed() 通知用戶。

    final class WebSocketWriter {. . . . . .void writeClose(int code, ByteString reason) throws IOException {ByteString payload = ByteString.EMPTY;if (code != 0 || reason != null) {if (code != 0) {validateCloseCode(code);}Buffer buffer = new Buffer();buffer.writeShort(code);if (reason != null) {buffer.write(reason);}payload = buffer.readByteString();}synchronized (this) {try {writeControlFrameSynchronized(OPCODE_CONTROL_CLOSE, payload);} finally {writerClosed = true;}}}

    將 CLOSE 幀發(fā)送到網(wǎng)絡(luò)的過(guò)程與 PING 和 PONG 幀的頗為相似,僅有的差別就是 CLOSE 幀有載荷。關(guān)于掩碼位和掩碼自己的規(guī)則,同樣適用于 CLOSE 幀的發(fā)送。

    CLOSE 的讀取在 WebSocketReader 的 readControlFrame()中:

    final class WebSocketReader {. . . . . .private void readControlFrame() throws IOException {Buffer buffer = new Buffer();if (frameBytesRead < frameLength) {if (isClient) {source.readFully(buffer, frameLength);} else {while (frameBytesRead < frameLength) {int toRead = (int) Math.min(frameLength - frameBytesRead, maskBuffer.length);int read = source.read(maskBuffer, 0, toRead);if (read == -1) throw new EOFException();toggleMask(maskBuffer, read, maskKey, frameBytesRead);buffer.write(maskBuffer, 0, read);frameBytesRead += read;}}}switch (opcode) {. . . . . .case OPCODE_CONTROL_CLOSE:int code = CLOSE_NO_STATUS_CODE;String reason = "";long bufferSize = buffer.size();if (bufferSize == 1) {throw new ProtocolException("Malformed close payload length of 1.");} else if (bufferSize != 0) {code = buffer.readShort();reason = buffer.readUtf8();String codeExceptionMessage = WebSocketProtocol.closeCodeExceptionMessage(code);if (codeExceptionMessage != null) throw new ProtocolException(codeExceptionMessage);}frameCallback.onReadClose(code, reason);closed = true;break;default:throw new ProtocolException("Unknown control opcode: " + toHexString(opcode));}}

    讀到 CLOSE 幀時(shí),WebSocketReader 會(huì)將這一事件通知出去:

    public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCallback {. . . . . .@Override public void onReadClose(int code, String reason) {if (code == -1) throw new IllegalArgumentException();Streams toClose = null;synchronized (this) {if (receivedCloseCode != -1) throw new IllegalStateException("already closed");receivedCloseCode = code;receivedCloseReason = reason;if (enqueuedClose && messageAndCloseQueue.isEmpty()) {toClose = this.streams;this.streams = null;if (cancelFuture != null) cancelFuture.cancel(false);this.executor.shutdown();}}try {listener.onClosing(this, code, reason);if (toClose != null) {listener.onClosed(this, code, reason);}} finally {closeQuietly(toClose);}}

    對(duì)于收到的 CLOSE 幀處理同樣分為主動(dòng)關(guān)閉的情況和被動(dòng)關(guān)閉的情況。與 CLOSE 發(fā)送時(shí)的情形正好相反,若是主動(dòng)關(guān)閉,則在收到 CLOSE 幀之后,WebSocket 連接最終斷開(kāi),因而需要停掉executor,被動(dòng)關(guān)閉則暫時(shí)不需要。

    收到 CLOSE 幀,總是會(huì)通過(guò) onClosing() 將事件通知出去。

    對(duì)于主動(dòng)關(guān)閉的情形,最后還會(huì)通過(guò) onClosed() 通知用戶,連接已經(jīng)最終關(guān)閉。

    關(guān)于 WebSocket 的 CLOSE 幀的更多說(shuō)明,可以參考 WebSocket協(xié)議規(guī)范。

    WebSocket連接的生命周期

    總結(jié)一下 WebSocket 連接的生命周期:

  • 連接通過(guò)一個(gè)HTTP請(qǐng)求握手并建立連接。WebSocket 連接可以理解為是通過(guò)HTTP請(qǐng)求建立的普通TCP連接。
  • WebSocket 做了二進(jìn)制分幀。WebSocket 連接中收發(fā)的數(shù)據(jù)以幀為單位。主要有用于連接保活的控制幀 PING 和 PONG,用于用戶數(shù)據(jù)發(fā)送的 MESSAGE 幀,和用于關(guān)閉連接的控制幀 CLOSE。
  • 連接建立之后,通過(guò) PING 幀和 PONG 幀做連接保活。
  • 一次 send 數(shù)據(jù),被封為一個(gè)消息,通過(guò)一個(gè)或多個(gè) MESSAGE幀進(jìn)行發(fā)送。一個(gè)消息的幀和控制幀可以交叉發(fā)送,不同消息的幀之間不可以。
  • WebSocket 連接的兩端相互發(fā)送一個(gè) CLOSE 幀以最終關(guān)閉連接。
  • 關(guān)于 WebSocket 的詳細(xì)信息,可以參考 WebSocket協(xié)議規(guī)范。

    參考文檔

    WebSocket 協(xié)議規(guī)范
    WebSocket 實(shí)戰(zhàn)
    使用 HTML5 WebSocket 構(gòu)建實(shí)時(shí) Web 應(yīng)用
    WebSocket Client Example with OkHttp

    總結(jié)

    以上是生活随笔為你收集整理的OkHttp实现分析之Websocket的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产精品久久精品三级 | 亚洲欧美日韩国产精品一区二区 | 性做久久久久久久免费看 | 狠狠色欧美亚洲狠狠色www | 九九热爱视频精品 | 久久久精品欧美一区二区免费 | 国产成人亚洲综合无码 | www一区二区www免费 | 成人试看120秒体验区 | 国产一区二区三区精品视频 | 国产精品99久久精品爆乳 | 欧美日韩人成综合在线播放 | 国产精品久久久久久久影院 | 女人被爽到呻吟gif动态图视看 | 99国产欧美久久久精品 | 亚洲成在人网站无码天堂 | 欧美性生交活xxxxxdddd | 欧美猛少妇色xxxxx | 婷婷色婷婷开心五月四房播播 | 成人精品视频一区二区三区尤物 | 一区二区传媒有限公司 | 精品水蜜桃久久久久久久 | 中文字幕人妻无码一夲道 | 国产激情艳情在线看视频 | 国产精品igao视频网 | 亚洲熟悉妇女xxx妇女av | 亚洲精品久久久久avwww潮水 | 国产精品亚洲五月天高清 | 亚洲欧美日韩成人高清在线一区 | 国产真人无遮挡作爱免费视频 | 青春草在线视频免费观看 | 图片区 小说区 区 亚洲五月 | 亚洲 激情 小说 另类 欧美 | 精品久久综合1区2区3区激情 | 色婷婷av一区二区三区之红樱桃 | 欧美猛少妇色xxxxx | 又紧又大又爽精品一区二区 | 特级做a爰片毛片免费69 | 亚洲天堂2017无码中文 | 成人免费视频视频在线观看 免费 | 欧美日韩亚洲国产精品 | 无码福利日韩神码福利片 | 婷婷综合久久中文字幕蜜桃三电影 | 少妇被粗大的猛进出69影院 | 欧美黑人性暴力猛交喷水 | 亚洲欧美日韩国产精品一区二区 | 久久精品中文闷骚内射 | 国产在线一区二区三区四区五区 | 老司机亚洲精品影院无码 | 国产成人无码a区在线观看视频app | 福利一区二区三区视频在线观看 | 人人爽人人澡人人高潮 | 国产亚洲精品久久久ai换 | 亚洲第一网站男人都懂 | 久激情内射婷内射蜜桃人妖 | 午夜无码区在线观看 | 无遮挡国产高潮视频免费观看 | 日本va欧美va欧美va精品 | 性色欲情网站iwww九文堂 | 99精品视频在线观看免费 | 丰满少妇人妻久久久久久 | 久久久久久久女国产乱让韩 | 亚洲欧美精品伊人久久 | 国产超碰人人爽人人做人人添 | 日本护士毛茸茸高潮 | 亚洲а∨天堂久久精品2021 | 亚洲国产日韩a在线播放 | 国产精品亚洲综合色区韩国 | 国产熟妇高潮叫床视频播放 | 国产又爽又猛又粗的视频a片 | 色妞www精品免费视频 | 婷婷丁香五月天综合东京热 | 久久久婷婷五月亚洲97号色 | 国产成人无码av片在线观看不卡 | 午夜理论片yy44880影院 | 成人三级无码视频在线观看 | 国内精品一区二区三区不卡 | a在线亚洲男人的天堂 | 亚洲七七久久桃花影院 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲色偷偷男人的天堂 | 国产精品香蕉在线观看 | 国内精品久久毛片一区二区 | 丰满妇女强制高潮18xxxx | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久久久国色av免费观看性色 | 久久精品国产一区二区三区 | 人妻有码中文字幕在线 | 四虎影视成人永久免费观看视频 | 在线天堂新版最新版在线8 | 麻豆国产人妻欲求不满 | 亚洲国产精品久久久天堂 | 1000部啪啪未满十八勿入下载 | 少妇无码av无码专区在线观看 | 亚洲爆乳无码专区 | 欧美xxxx黑人又粗又长 | 欧美日本免费一区二区三区 | 精品一区二区三区波多野结衣 | 人妻少妇精品无码专区动漫 | 午夜丰满少妇性开放视频 | 天天摸天天透天天添 | 99久久精品午夜一区二区 | 好男人www社区 | 77777熟女视频在线观看 а天堂中文在线官网 | 少妇太爽了在线观看 | 亚洲综合久久一区二区 | 久久久久久av无码免费看大片 | 亚洲国产av美女网站 | 午夜福利一区二区三区在线观看 | 夫妻免费无码v看片 | 成人欧美一区二区三区黑人 | 老司机亚洲精品影院 | 性欧美牲交xxxxx视频 | av香港经典三级级 在线 | 最新国产麻豆aⅴ精品无码 | 无码一区二区三区在线 | 无码一区二区三区在线观看 | 漂亮人妻洗澡被公强 日日躁 | 久久久久99精品国产片 | 国产亚洲精品久久久久久国模美 | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲の无码国产の无码影院 | 亚洲小说春色综合另类 | 精品午夜福利在线观看 | 色一情一乱一伦一视频免费看 | 亚洲第一无码av无码专区 | 欧美人与善在线com | 国产精品亚洲一区二区三区喷水 | 又大又硬又黄的免费视频 | 亚洲国产精品无码一区二区三区 | 国产精品亚洲专区无码不卡 | 亚洲va欧美va天堂v国产综合 | 久久久久久av无码免费看大片 | 少妇性荡欲午夜性开放视频剧场 | 亚洲欧美色中文字幕在线 | 精品日本一区二区三区在线观看 | 亚洲小说春色综合另类 | 亚洲国产精品美女久久久久 | 国产69精品久久久久app下载 | 免费男性肉肉影院 | 小鲜肉自慰网站xnxx | 亚洲日本一区二区三区在线 | 97久久国产亚洲精品超碰热 | 亚洲区小说区激情区图片区 | 无码人中文字幕 | 亚洲gv猛男gv无码男同 | 奇米影视888欧美在线观看 | 亚洲欧美日韩成人高清在线一区 | 1000部啪啪未满十八勿入下载 | 内射巨臀欧美在线视频 | 国产69精品久久久久app下载 | 久久久婷婷五月亚洲97号色 | 日韩精品a片一区二区三区妖精 | 99久久精品午夜一区二区 | 久久久久se色偷偷亚洲精品av | 少妇愉情理伦片bd | 国产乱人偷精品人妻a片 | 亚洲人亚洲人成电影网站色 | 四虎国产精品免费久久 | 丝袜人妻一区二区三区 | 亚洲一区二区三区四区 | 天堂亚洲2017在线观看 | 国产又爽又猛又粗的视频a片 | 在线观看免费人成视频 | 一本大道久久东京热无码av | 欧美日本免费一区二区三区 | 人妻尝试又大又粗久久 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲中文字幕va福利 | 99久久精品国产一区二区蜜芽 | 国产激情无码一区二区app | 精品国产av色一区二区深夜久久 | 人人妻人人澡人人爽欧美精品 | 久久精品丝袜高跟鞋 | 日日鲁鲁鲁夜夜爽爽狠狠 | 成人片黄网站色大片免费观看 | 免费国产成人高清在线观看网站 | 欧美肥老太牲交大战 | 日产精品高潮呻吟av久久 | 国产一区二区三区四区五区加勒比 | 午夜精品久久久久久久久 | 鲁一鲁av2019在线 | 东京无码熟妇人妻av在线网址 | 久久亚洲国产成人精品性色 | 九一九色国产 | 激情爆乳一区二区三区 | 亚洲中文字幕无码中文字在线 | 亚洲精品www久久久 | 日韩欧美中文字幕公布 | 欧美性猛交内射兽交老熟妇 | 欧美丰满熟妇xxxx性ppx人交 | 色一情一乱一伦一区二区三欧美 | 欧美人与牲动交xxxx | 亚洲中文字幕久久无码 | 国精品人妻无码一区二区三区蜜柚 | 夜夜夜高潮夜夜爽夜夜爰爰 | 丰满肥臀大屁股熟妇激情视频 | 麻豆蜜桃av蜜臀av色欲av | 免费看男女做好爽好硬视频 | 撕开奶罩揉吮奶头视频 | 色综合久久久无码网中文 | 伊人色综合久久天天小片 | 麻豆果冻传媒2021精品传媒一区下载 | 中国女人内谢69xxxxxa片 | 99riav国产精品视频 | 中文字幕久久久久人妻 | 久久国内精品自在自线 | 麻豆国产人妻欲求不满谁演的 | 久久亚洲中文字幕精品一区 | 国产极品视觉盛宴 | 精品一二三区久久aaa片 | 永久免费精品精品永久-夜色 | 国产特级毛片aaaaaa高潮流水 | 偷窥日本少妇撒尿chinese | 中文字幕乱码人妻无码久久 | 国产特级毛片aaaaaa高潮流水 | 麻豆国产97在线 | 欧洲 | 精品国产一区二区三区av 性色 | 免费人成网站视频在线观看 | 亚洲七七久久桃花影院 | 国内精品久久毛片一区二区 | 波多野42部无码喷潮在线 | 扒开双腿疯狂进出爽爽爽视频 | 欧洲极品少妇 | 一本色道久久综合狠狠躁 | 亚洲欧洲日本无在线码 | 97人妻精品一区二区三区 | 亚洲色偷偷男人的天堂 | 国产又爽又猛又粗的视频a片 | av在线亚洲欧洲日产一区二区 | 国产精品va在线观看无码 | 妺妺窝人体色www婷婷 | 亚洲 另类 在线 欧美 制服 | 精品久久8x国产免费观看 | 亚洲色大成网站www国产 | 国产精品对白交换视频 | 少妇人妻大乳在线视频 | 少妇性l交大片 | 久久久久国色av免费观看性色 | 日韩欧美群交p片內射中文 | 亚洲七七久久桃花影院 | 亚洲男人av香蕉爽爽爽爽 | 亚洲男女内射在线播放 | 国产精品亚洲一区二区三区喷水 | 日本乱人伦片中文三区 | 中文精品无码中文字幕无码专区 | 国产又爽又猛又粗的视频a片 | 久久www免费人成人片 | 成人aaa片一区国产精品 | 97资源共享在线视频 | 国产亚洲精品精品国产亚洲综合 | 午夜精品久久久久久久 | 7777奇米四色成人眼影 | 无码人妻丰满熟妇区毛片18 | 免费中文字幕日韩欧美 | 日本xxxx色视频在线观看免费 | 熟妇人妻无码xxx视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 人人妻人人澡人人爽欧美一区九九 | 亚洲毛片av日韩av无码 | 亚洲区小说区激情区图片区 | 图片区 小说区 区 亚洲五月 | 蜜桃无码一区二区三区 | 国产莉萝无码av在线播放 | 亚洲国产高清在线观看视频 | 亚洲精品无码国产 | 在线观看欧美一区二区三区 | 中文无码伦av中文字幕 | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲色欲久久久综合网东京热 | 国产成人午夜福利在线播放 | 国产av人人夜夜澡人人爽麻豆 | 天堂亚洲2017在线观看 | 国产美女极度色诱视频www | 欧美激情一区二区三区成人 | 人妻人人添人妻人人爱 | 欧美性生交活xxxxxdddd | 日欧一片内射va在线影院 | 午夜无码区在线观看 | 精品亚洲成av人在线观看 | 日日天干夜夜狠狠爱 | 亚洲国产欧美日韩精品一区二区三区 | 日韩精品a片一区二区三区妖精 | 夜夜影院未满十八勿进 | 精品亚洲成av人在线观看 | 亚洲中文字幕在线无码一区二区 | 丰满少妇熟乱xxxxx视频 | 精品aⅴ一区二区三区 | 永久免费观看国产裸体美女 | av在线亚洲欧洲日产一区二区 | 装睡被陌生人摸出水好爽 | 宝宝好涨水快流出来免费视频 | 一二三四在线观看免费视频 | 中文字幕无码av波多野吉衣 | 97资源共享在线视频 | 亚洲国产欧美国产综合一区 | 欧洲欧美人成视频在线 | 中文字幕无码免费久久9一区9 | 久久亚洲精品中文字幕无男同 | 亚洲a无码综合a国产av中文 | 在线观看欧美一区二区三区 | 在线观看国产午夜福利片 | 国产亚洲精品久久久ai换 | 两性色午夜视频免费播放 | 国产精品香蕉在线观看 | 亚洲a无码综合a国产av中文 | 精品国产青草久久久久福利 | 久9re热视频这里只有精品 | 国产成人一区二区三区在线观看 | 亚洲精品综合五月久久小说 | 久久久久久久女国产乱让韩 | 久久久久se色偷偷亚洲精品av | 国产午夜福利亚洲第一 | 免费无码的av片在线观看 | 色一情一乱一伦一区二区三欧美 | 欧美自拍另类欧美综合图片区 | 亚洲七七久久桃花影院 | 国产成人无码区免费内射一片色欲 | 人人爽人人爽人人片av亚洲 | 精品国产国产综合精品 | 国产av无码专区亚洲a∨毛片 | 天天综合网天天综合色 | 日韩精品无码一区二区中文字幕 | 久久www免费人成人片 | 特黄特色大片免费播放器图片 | 永久黄网站色视频免费直播 | 中国女人内谢69xxxxxa片 | 亚洲精品www久久久 | 久久国产36精品色熟妇 | 玩弄少妇高潮ⅹxxxyw | 亚洲午夜福利在线观看 | av无码电影一区二区三区 | 中文字幕久久久久人妻 | 欧美日韩一区二区三区自拍 | 在线播放无码字幕亚洲 | 无套内射视频囯产 | 欧美丰满老熟妇xxxxx性 | 97精品人妻一区二区三区香蕉 | 性欧美videos高清精品 | 性色av无码免费一区二区三区 | 国产精品久免费的黄网站 | 久激情内射婷内射蜜桃人妖 | 18禁黄网站男男禁片免费观看 | 精品夜夜澡人妻无码av蜜桃 | 蜜臀av在线播放 久久综合激激的五月天 | 久久久精品人妻久久影视 | 大肉大捧一进一出好爽视频 | 人妻少妇精品视频专区 | 国模大胆一区二区三区 | 黑人巨大精品欧美一区二区 | 欧美自拍另类欧美综合图片区 | 免费观看又污又黄的网站 | 亚洲乱码中文字幕在线 | 女人被爽到呻吟gif动态图视看 | 国产成人一区二区三区在线观看 | 十八禁真人啪啪免费网站 | 午夜精品一区二区三区在线观看 | 精品无码国产自产拍在线观看蜜 | 亚洲精品综合一区二区三区在线 | 国产电影无码午夜在线播放 | 三上悠亚人妻中文字幕在线 | 色噜噜亚洲男人的天堂 | 亚洲人成网站色7799 | 清纯唯美经典一区二区 | 国产成人精品优优av | 熟妇人妻无码xxx视频 | 99久久99久久免费精品蜜桃 | 国语自产偷拍精品视频偷 | 无码av免费一区二区三区试看 | 性欧美videos高清精品 | 少妇愉情理伦片bd | 国产亚av手机在线观看 | 日本成熟视频免费视频 | 亚洲高清偷拍一区二区三区 | 久久久亚洲欧洲日产国码αv | 精品国产aⅴ无码一区二区 | 欧洲vodafone精品性 | 狂野欧美性猛xxxx乱大交 | 无码精品国产va在线观看dvd | 狠狠色噜噜狠狠狠狠7777米奇 | 天堂а√在线地址中文在线 | 亚洲国产综合无码一区 | 青青久在线视频免费观看 | 免费乱码人妻系列无码专区 | 久久精品女人天堂av免费观看 | 欧美老熟妇乱xxxxx | 国产亚洲精品久久久久久久久动漫 | 亚洲精品www久久久 | 国产成人人人97超碰超爽8 | 精品人妻人人做人人爽夜夜爽 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲第一无码av无码专区 | 激情综合激情五月俺也去 | 国产成人一区二区三区别 | 丰满妇女强制高潮18xxxx | 久久伊人色av天堂九九小黄鸭 | 欧美一区二区三区视频在线观看 | 中文字幕人妻无码一夲道 | 在线а√天堂中文官网 | 六月丁香婷婷色狠狠久久 | 久久亚洲精品中文字幕无男同 | 亚洲欧洲日本综合aⅴ在线 | 日本丰满护士爆乳xxxx | 久久精品国产一区二区三区 | 网友自拍区视频精品 | 国产成人精品无码播放 | 漂亮人妻洗澡被公强 日日躁 | 国产精品国产自线拍免费软件 | 欧美成人午夜精品久久久 | 九九久久精品国产免费看小说 | 国产精品a成v人在线播放 | 国产卡一卡二卡三 | 亚洲色偷偷男人的天堂 | 天海翼激烈高潮到腰振不止 | 精品国产一区二区三区四区在线看 | 中文字幕av伊人av无码av | 日本熟妇大屁股人妻 | 久久久久99精品成人片 | 老熟女乱子伦 | 男女爱爱好爽视频免费看 | 精品熟女少妇av免费观看 | 国产综合色产在线精品 | 国产av无码专区亚洲awww | 久久国产自偷自偷免费一区调 | 成 人 网 站国产免费观看 | 麻豆精产国品 | 亚洲综合伊人久久大杳蕉 | 天下第一社区视频www日本 | 又色又爽又黄的美女裸体网站 | 少妇无码av无码专区在线观看 | 亚洲区欧美区综合区自拍区 | 亚洲成a人片在线观看无码 | 欧美激情内射喷水高潮 | 麻豆md0077饥渴少妇 | 精品一区二区三区波多野结衣 | 一本加勒比波多野结衣 | 久久久久久九九精品久 | 精品国产青草久久久久福利 | √天堂中文官网8在线 | 久久久久人妻一区精品色欧美 | 国产午夜手机精彩视频 | 亚洲精品综合五月久久小说 | 麻豆精品国产精华精华液好用吗 | 欧美日韩色另类综合 | 欧美午夜特黄aaaaaa片 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 人妻少妇精品无码专区二区 | 99国产精品白浆在线观看免费 | 性生交片免费无码看人 | 无码人妻少妇伦在线电影 | 久久熟妇人妻午夜寂寞影院 | 亚洲人成人无码网www国产 | 无码帝国www无码专区色综合 | 特黄特色大片免费播放器图片 | 国产精品99爱免费视频 | 国产午夜亚洲精品不卡 | 国模大胆一区二区三区 | 精品国产成人一区二区三区 | 性色av无码免费一区二区三区 | 亚洲人亚洲人成电影网站色 | 国产精品久久久av久久久 | 人妻体内射精一区二区三四 | 午夜不卡av免费 一本久久a久久精品vr综合 | 精品人妻中文字幕有码在线 | 西西人体www44rt大胆高清 | 又粗又大又硬又长又爽 | 白嫩日本少妇做爰 | 最新国产麻豆aⅴ精品无码 | v一区无码内射国产 | 久久99精品国产.久久久久 | 国产福利视频一区二区 | 久久久久av无码免费网 | 精品夜夜澡人妻无码av蜜桃 | 一本色道婷婷久久欧美 | 国产绳艺sm调教室论坛 | 76少妇精品导航 | 中文字幕亚洲情99在线 | 牲欲强的熟妇农村老妇女视频 | 久久aⅴ免费观看 | 人妻体内射精一区二区三四 | 人人澡人摸人人添 | 国产精品久久久久久久影院 | 老司机亚洲精品影院 | 小泽玛莉亚一区二区视频在线 | 99er热精品视频 | 任你躁在线精品免费 | 精品久久久中文字幕人妻 | 天天综合网天天综合色 | 中文字幕无线码免费人妻 | 国产精品手机免费 | 欧美老熟妇乱xxxxx | 成人精品天堂一区二区三区 | 国产精品沙发午睡系列 | 在线视频网站www色 | 精品国产青草久久久久福利 | 日韩欧美成人免费观看 | 丰满少妇人妻久久久久久 | 欧美国产亚洲日韩在线二区 | 欧美三级a做爰在线观看 | 午夜肉伦伦影院 | 亚洲一区二区三区四区 | 欧美日韩精品 | 精品一二三区久久aaa片 | 国产亚洲视频中文字幕97精品 | 美女扒开屁股让男人桶 | 男人的天堂2018无码 | 东京一本一道一二三区 | 精品厕所偷拍各类美女tp嘘嘘 | 丰满人妻一区二区三区免费视频 | 亚洲精品一区三区三区在线观看 | 国产精品亚洲综合色区韩国 | 中文无码精品a∨在线观看不卡 | 精品国产aⅴ无码一区二区 | 亚洲成a人片在线观看日本 | 亚洲成av人在线观看网址 | 欧美精品一区二区精品久久 | 天堂无码人妻精品一区二区三区 | 久久久久人妻一区精品色欧美 | 国产欧美精品一区二区三区 | 国产精品人人妻人人爽 | 少妇的肉体aa片免费 | 日韩人妻系列无码专区 | 男女下面进入的视频免费午夜 | 水蜜桃av无码 | 1000部夫妻午夜免费 | 亚洲综合精品香蕉久久网 | 欧美老妇与禽交 | 台湾无码一区二区 | 午夜时刻免费入口 | 最近免费中文字幕中文高清百度 | 131美女爱做视频 | 亚洲 日韩 欧美 成人 在线观看 | 无码国模国产在线观看 | 女人被爽到呻吟gif动态图视看 | 国产无遮挡又黄又爽又色 | 丰满人妻被黑人猛烈进入 | 捆绑白丝粉色jk震动捧喷白浆 | 3d动漫精品啪啪一区二区中 | 欧美日韩一区二区三区自拍 | 欧美野外疯狂做受xxxx高潮 | 国内精品久久久久久中文字幕 | 好男人www社区 | 国产成人精品久久亚洲高清不卡 | 九月婷婷人人澡人人添人人爽 | 国产在热线精品视频 | 日日摸日日碰夜夜爽av | 狠狠色欧美亚洲狠狠色www | 欧美人与动性行为视频 | 日本熟妇大屁股人妻 | 久久久久久久女国产乱让韩 | 日日天日日夜日日摸 | 暴力强奷在线播放无码 | 欧美激情内射喷水高潮 | 国产黄在线观看免费观看不卡 | 久久午夜无码鲁丝片秋霞 | 男人的天堂2018无码 | 97资源共享在线视频 | 亚洲精品国产a久久久久久 | 六月丁香婷婷色狠狠久久 | 国产精品人妻一区二区三区四 | 国产成人无码av片在线观看不卡 | 亚洲精品国产精品乱码不卡 | 久久久久成人精品免费播放动漫 | 欧美 亚洲 国产 另类 | 一本色道婷婷久久欧美 | 亚洲欧美精品aaaaaa片 | 秋霞成人午夜鲁丝一区二区三区 | 久久久久人妻一区精品色欧美 | 天干天干啦夜天干天2017 | 色婷婷香蕉在线一区二区 | 蜜臀av在线播放 久久综合激激的五月天 | www国产精品内射老师 | 精品无码av一区二区三区 | 亚无码乱人伦一区二区 | 国产精品久久国产精品99 | 国产色xx群视频射精 | 欧美成人家庭影院 | 中文字幕精品av一区二区五区 | 大色综合色综合网站 | 亚洲人成网站在线播放942 | 亚洲 日韩 欧美 成人 在线观看 | 小泽玛莉亚一区二区视频在线 | 人妻体内射精一区二区三四 | 国产激情精品一区二区三区 | 日韩欧美中文字幕公布 | 精品乱码久久久久久久 | 精品国产国产综合精品 | 久久婷婷五月综合色国产香蕉 | 久久五月精品中文字幕 | 欧美丰满熟妇xxxx | 狠狠色色综合网站 | 成人aaa片一区国产精品 | 性欧美牲交xxxxx视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 亚洲国产精品久久久天堂 | 欧美激情一区二区三区成人 | 亚洲中文字幕成人无码 | 日韩精品无码免费一区二区三区 | 色综合久久久无码网中文 | 色婷婷欧美在线播放内射 | 久久亚洲中文字幕无码 | 乱人伦人妻中文字幕无码 | 麻豆果冻传媒2021精品传媒一区下载 | 狠狠综合久久久久综合网 | 精品无码av一区二区三区 | 久久久中文字幕日本无吗 | 国产精品嫩草久久久久 | 国产欧美精品一区二区三区 | 欧美阿v高清资源不卡在线播放 | 国产深夜福利视频在线 | 成人精品一区二区三区中文字幕 | 国产人妻精品一区二区三区 | 亚洲国产成人av在线观看 | 九九综合va免费看 | 欧美喷潮久久久xxxxx | 无码人妻久久一区二区三区不卡 | 国产无套内射久久久国产 | 色偷偷人人澡人人爽人人模 | 国产成人无码午夜视频在线观看 | 欧美老熟妇乱xxxxx | 国产精品99爱免费视频 | 性欧美videos高清精品 | 亚洲小说图区综合在线 | 中国女人内谢69xxxx | 黑人巨大精品欧美黑寡妇 | 欧美老熟妇乱xxxxx | 久久婷婷五月综合色国产香蕉 | 亚洲欧美国产精品专区久久 | 国色天香社区在线视频 | 亚洲啪av永久无码精品放毛片 | 欧美刺激性大交 | 亚洲欧美综合区丁香五月小说 | 国产亚洲精品久久久久久久久动漫 | 日韩精品无码免费一区二区三区 | 天天燥日日燥 | 人妻天天爽夜夜爽一区二区 | 中文字幕人成乱码熟女app | 3d动漫精品啪啪一区二区中 | 亚洲日韩av一区二区三区四区 | 免费国产黄网站在线观看 | 午夜免费福利小电影 | 76少妇精品导航 | 成人精品视频一区二区 | 亚洲天堂2017无码中文 | 亚洲自偷自偷在线制服 | 99久久人妻精品免费一区 | 成人一区二区免费视频 | 亚洲一区二区三区播放 | 人人妻人人澡人人爽欧美一区九九 | 国产成人精品视频ⅴa片软件竹菊 | 国产精品-区区久久久狼 | 国产成人无码一二三区视频 | 少妇的肉体aa片免费 | 人妻插b视频一区二区三区 | 午夜时刻免费入口 | 久久成人a毛片免费观看网站 | 国产另类ts人妖一区二区 | 国产99久久精品一区二区 | 国产一区二区三区日韩精品 | 精品国产乱码久久久久乱码 | 日韩精品一区二区av在线 | 水蜜桃亚洲一二三四在线 | 亚洲精品一区二区三区婷婷月 | 国产精品第一区揄拍无码 | 日韩av无码中文无码电影 | 女人被男人爽到呻吟的视频 | 国产免费无码一区二区视频 | 中文字幕av日韩精品一区二区 | 在线看片无码永久免费视频 | 日本护士xxxxhd少妇 | 波多野结衣 黑人 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久久久久久人妻无码中文字幕爆 | 午夜免费福利小电影 | 国产人妖乱国产精品人妖 | 俺去俺来也在线www色官网 | 国产农村妇女高潮大叫 | 水蜜桃亚洲一二三四在线 | 国产 浪潮av性色四虎 | 国产免费久久精品国产传媒 | 国产亚洲tv在线观看 | 国产午夜无码精品免费看 | 夜夜躁日日躁狠狠久久av | 偷窥日本少妇撒尿chinese | 久久亚洲a片com人成 | 欧美喷潮久久久xxxxx | 亚洲精品欧美二区三区中文字幕 | 成人无码精品1区2区3区免费看 | 秋霞成人午夜鲁丝一区二区三区 | 日本丰满熟妇videos | 国产精品办公室沙发 | 日本一区二区三区免费高清 | 久久久中文字幕日本无吗 | 永久免费观看美女裸体的网站 | 国产午夜福利100集发布 | www国产亚洲精品久久久日本 | 国产精品无码mv在线观看 | 国产成人精品无码播放 | 欧洲精品码一区二区三区免费看 | 人人妻人人澡人人爽欧美一区 | 一本大道伊人av久久综合 | 色综合久久久无码中文字幕 | 精品日本一区二区三区在线观看 | 国产99久久精品一区二区 | 国内丰满熟女出轨videos | 亚洲无人区午夜福利码高清完整版 | 欧美日韩一区二区免费视频 | 国产猛烈高潮尖叫视频免费 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲熟熟妇xxxx | 一本久久a久久精品亚洲 | 国产亚洲tv在线观看 | 亚洲小说春色综合另类 | 亚洲七七久久桃花影院 | 精品成人av一区二区三区 | 精品夜夜澡人妻无码av蜜桃 | 性欧美大战久久久久久久 | aⅴ亚洲 日韩 色 图网站 播放 | 国产美女极度色诱视频www | 装睡被陌生人摸出水好爽 | 中文字幕无线码免费人妻 | 成人性做爰aaa片免费看 | 国产激情无码一区二区 | 2020久久超碰国产精品最新 | 欧美国产亚洲日韩在线二区 | 国产偷抇久久精品a片69 | 国产精品办公室沙发 | 亚洲熟女一区二区三区 | 纯爱无遮挡h肉动漫在线播放 | 影音先锋中文字幕无码 | 76少妇精品导航 | 久久无码专区国产精品s | 亚洲自偷自偷在线制服 | 97se亚洲精品一区 | 日日摸夜夜摸狠狠摸婷婷 | 精品国产乱码久久久久乱码 | 蜜臀aⅴ国产精品久久久国产老师 | 久久精品国产一区二区三区 | 美女黄网站人色视频免费国产 | 亚洲色在线无码国产精品不卡 | 一本久道久久综合婷婷五月 | 国产女主播喷水视频在线观看 | 国产精品.xx视频.xxtv | 亚洲日本一区二区三区在线 | 久久久久成人精品免费播放动漫 | 色综合久久网 | 无码av岛国片在线播放 | 99麻豆久久久国产精品免费 | 日本乱人伦片中文三区 | 亚洲欧美国产精品久久 | 国产无遮挡又黄又爽又色 | 少妇人妻av毛片在线看 | 扒开双腿疯狂进出爽爽爽视频 | 中文字幕av伊人av无码av | 中文字幕精品av一区二区五区 | 少妇无码一区二区二三区 | 亚洲一区二区三区四区 | 亚洲熟女一区二区三区 | 日本xxxx色视频在线观看免费 | 国产精品内射视频免费 | 久久无码中文字幕免费影院蜜桃 | 久久五月精品中文字幕 | 一本久久a久久精品vr综合 | 成人欧美一区二区三区 | 成人精品视频一区二区三区尤物 | 色狠狠av一区二区三区 | aⅴ亚洲 日韩 色 图网站 播放 | 夜夜高潮次次欢爽av女 | 午夜不卡av免费 一本久久a久久精品vr综合 | 国产成人综合色在线观看网站 | 久久久精品国产sm最大网站 | 内射爽无广熟女亚洲 | 六月丁香婷婷色狠狠久久 | 国产精品久久精品三级 | 日本乱偷人妻中文字幕 | 色欲人妻aaaaaaa无码 | 亚洲国产高清在线观看视频 | 国产激情综合五月久久 | 日本xxxx色视频在线观看免费 | 性做久久久久久久免费看 | 红桃av一区二区三区在线无码av | 夜先锋av资源网站 | 日本一卡二卡不卡视频查询 | 一本色道久久综合亚洲精品不卡 | 清纯唯美经典一区二区 | 俄罗斯老熟妇色xxxx | 免费人成网站视频在线观看 | 久久久精品成人免费观看 | 桃花色综合影院 | 激情爆乳一区二区三区 | 亚洲国产成人av在线观看 | 亚洲人成网站在线播放942 | 中文字幕久久久久人妻 | 中文毛片无遮挡高清免费 | 日产国产精品亚洲系列 | 亚洲成av人影院在线观看 | 成人无码精品1区2区3区免费看 | 欧美日韩一区二区三区自拍 | 亚洲区欧美区综合区自拍区 | 色综合天天综合狠狠爱 | 日韩人妻无码一区二区三区久久99 | 动漫av一区二区在线观看 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲国产精品一区二区美利坚 | 亚洲欧洲无卡二区视頻 | 日本高清一区免费中文视频 | 黑人巨大精品欧美黑寡妇 | 天堂а√在线地址中文在线 | 成人动漫在线观看 | 欧美 日韩 人妻 高清 中文 | 一本久道久久综合狠狠爱 | 亚洲小说图区综合在线 | 中文字幕无码人妻少妇免费 | 亚洲日韩乱码中文无码蜜桃臀网站 | 成人无码视频免费播放 | 成在人线av无码免观看麻豆 | 亚洲精品久久久久久一区二区 | 欧美人与禽猛交狂配 | 午夜精品久久久内射近拍高清 | 国产精品嫩草久久久久 | 亚洲va欧美va天堂v国产综合 | 骚片av蜜桃精品一区 | 久久 国产 尿 小便 嘘嘘 | 国产性生交xxxxx无码 | 久久国产精品精品国产色婷婷 | 中文字幕av日韩精品一区二区 | 亚洲一区av无码专区在线观看 | 久久无码中文字幕免费影院蜜桃 | 国产无av码在线观看 | 国产免费观看黄av片 | 人人妻人人澡人人爽欧美精品 | 欧美 丝袜 自拍 制服 另类 | 精品国产一区av天美传媒 | 久久久精品人妻久久影视 | 久久伊人色av天堂九九小黄鸭 | 狠狠色欧美亚洲狠狠色www | 久久www免费人成人片 | 久久久久se色偷偷亚洲精品av | 永久免费观看美女裸体的网站 | 久久人人爽人人人人片 | 正在播放老肥熟妇露脸 | 日本va欧美va欧美va精品 | 日韩精品一区二区av在线 | 国产内射老熟女aaaa | 国产在线精品一区二区三区直播 | 国产两女互慰高潮视频在线观看 | 少妇被黑人到高潮喷出白浆 | 99re在线播放 | 免费无码肉片在线观看 | 免费观看又污又黄的网站 | 中文字幕无码视频专区 | 亚洲成熟女人毛毛耸耸多 | 亚洲综合无码久久精品综合 | 高清无码午夜福利视频 | 久久国语露脸国产精品电影 | 久青草影院在线观看国产 | 成人aaa片一区国产精品 | 欧美真人作爱免费视频 | 中文字幕亚洲情99在线 | 曰韩无码二三区中文字幕 | 国产精品高潮呻吟av久久 | 亚洲综合久久一区二区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 日本肉体xxxx裸交 | 日日麻批免费40分钟无码 | 久久99国产综合精品 | 国产免费无码一区二区视频 | 日韩视频 中文字幕 视频一区 | 伊人久久大香线蕉亚洲 | 久久精品国产99久久6动漫 | 久久熟妇人妻午夜寂寞影院 | 永久免费观看美女裸体的网站 | 色欲久久久天天天综合网精品 | 丝袜足控一区二区三区 | 少妇久久久久久人妻无码 | 99久久久无码国产精品免费 | 精品久久久久久人妻无码中文字幕 | 无码毛片视频一区二区本码 | 亚洲国产成人a精品不卡在线 | 乱码av麻豆丝袜熟女系列 | 亚洲精品一区二区三区在线观看 | 一个人看的www免费视频在线观看 | 婷婷综合久久中文字幕蜜桃三电影 | 人妻尝试又大又粗久久 | 日本护士xxxxhd少妇 | 领导边摸边吃奶边做爽在线观看 | 亚洲精品一区二区三区在线 | 牛和人交xxxx欧美 | 最近的中文字幕在线看视频 | 欧美人妻一区二区三区 | 国产色精品久久人妻 | 色一情一乱一伦 | 日韩少妇白浆无码系列 | 丁香啪啪综合成人亚洲 | 青青草原综合久久大伊人精品 | 久久人人爽人人人人片 | 亚洲一区二区三区含羞草 | 蜜臀av在线播放 久久综合激激的五月天 | 久久久久人妻一区精品色欧美 | 亚洲一区二区三区无码久久 | 日本成熟视频免费视频 | 三上悠亚人妻中文字幕在线 | 超碰97人人射妻 | 久久熟妇人妻午夜寂寞影院 | 国产片av国语在线观看 | a国产一区二区免费入口 | 天天综合网天天综合色 | 日韩av无码一区二区三区不卡 | 日本欧美一区二区三区乱码 | 精品国产成人一区二区三区 | 亚洲小说图区综合在线 | 亚洲午夜久久久影院 | 色综合久久88色综合天天 | 久久国产自偷自偷免费一区调 | 精品欧洲av无码一区二区三区 | 国产人妖乱国产精品人妖 | 精品久久8x国产免费观看 | 国产精华av午夜在线观看 | 国产成人一区二区三区别 | 男女下面进入的视频免费午夜 | 在线观看国产午夜福利片 | 亚洲中文字幕va福利 | 午夜丰满少妇性开放视频 | 亚洲自偷自拍另类第1页 | 国产97在线 | 亚洲 | 国产亚洲欧美在线专区 | 亚洲人成人无码网www国产 | 欧美亚洲国产一区二区三区 | 无码人妻出轨黑人中文字幕 | 300部国产真实乱 | 欧美国产日韩亚洲中文 | 欧美激情综合亚洲一二区 | 国产亚洲精品久久久久久久 | 国模大胆一区二区三区 | 伊人久久婷婷五月综合97色 | 欧美人与物videos另类 | 日韩人妻无码一区二区三区久久99 | 亚洲国产一区二区三区在线观看 | 国产另类ts人妖一区二区 | 狠狠色丁香久久婷婷综合五月 | 澳门永久av免费网站 | 午夜福利不卡在线视频 | 日本肉体xxxx裸交 | 无码中文字幕色专区 | 老熟妇仑乱视频一区二区 | 老子影院午夜伦不卡 | 国内精品久久毛片一区二区 | 国内综合精品午夜久久资源 | 无码纯肉视频在线观看 | 亚洲中文字幕无码中文字在线 | 牲欲强的熟妇农村老妇女 | 精品久久久中文字幕人妻 | 中国大陆精品视频xxxx | 一二三四社区在线中文视频 | 欧美性生交活xxxxxdddd | 久久久精品欧美一区二区免费 | 奇米影视888欧美在线观看 | 久久国产精品_国产精品 | 国产精品久久久久久久影院 | 成人无码影片精品久久久 | 无码一区二区三区在线观看 | 伊人久久大香线蕉av一区二区 | ass日本丰满熟妇pics | 免费观看激色视频网站 | 久久精品人人做人人综合试看 | 日韩精品无码一本二本三本色 | 风流少妇按摩来高潮 | 欧美肥老太牲交大战 | 强伦人妻一区二区三区视频18 | 国产精品永久免费视频 | 影音先锋中文字幕无码 | 国产一区二区三区四区五区加勒比 | 国产精品办公室沙发 | 久久久av男人的天堂 | 夫妻免费无码v看片 | 亚洲成av人影院在线观看 | 亚洲中文无码av永久不收费 | 国产内射老熟女aaaa | 亚洲精品中文字幕乱码 | 亚洲综合无码久久精品综合 | 欧美自拍另类欧美综合图片区 | 亚洲中文字幕久久无码 | 亚洲娇小与黑人巨大交 | 欧美国产日韩亚洲中文 | 国产在线无码精品电影网 | 天天爽夜夜爽夜夜爽 | 日本www一道久久久免费榴莲 | 激情内射日本一区二区三区 | 国产深夜福利视频在线 | 国产一区二区三区四区五区加勒比 | 人人澡人人透人人爽 | 亚洲熟女一区二区三区 | 九九综合va免费看 | 无码人妻精品一区二区三区不卡 | 激情内射日本一区二区三区 | 欧美成人免费全部网站 | 又粗又大又硬毛片免费看 | 性色欲网站人妻丰满中文久久不卡 | 强开小婷嫩苞又嫩又紧视频 | 3d动漫精品啪啪一区二区中 | 久久久亚洲欧洲日产国码αv | 999久久久国产精品消防器材 | 国产av无码专区亚洲a∨毛片 | 中文字幕中文有码在线 | 麻豆精产国品 | 国产精品99久久精品爆乳 | 久久精品女人天堂av免费观看 | 天海翼激烈高潮到腰振不止 | 国产成人无码a区在线观看视频app | 成人aaa片一区国产精品 | 欧美兽交xxxx×视频 | 麻豆国产丝袜白领秘书在线观看 | 人妻熟女一区 | 国产一区二区三区影院 | 在线观看国产一区二区三区 | 中文字幕无线码免费人妻 | 久精品国产欧美亚洲色aⅴ大片 | 色婷婷香蕉在线一区二区 | 激情内射亚州一区二区三区爱妻 | 欧洲熟妇精品视频 | 一本色道久久综合亚洲精品不卡 | 国产精品成人av在线观看 | 亚洲性无码av中文字幕 | 98国产精品综合一区二区三区 | 丰满少妇熟乱xxxxx视频 | 大屁股大乳丰满人妻 | 图片区 小说区 区 亚洲五月 | 免费播放一区二区三区 | 欧美怡红院免费全部视频 | 欧美成人高清在线播放 | 黑人粗大猛烈进出高潮视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | 国产精品理论片在线观看 | 亚洲日本va午夜在线电影 | 人妻少妇精品无码专区动漫 | 久久久久se色偷偷亚洲精品av | 又大又黄又粗又爽的免费视频 | 欧美日韩人成综合在线播放 | 国产精品亚洲综合色区韩国 | 天天做天天爱天天爽综合网 | 亚洲欧美综合区丁香五月小说 | 成人精品一区二区三区中文字幕 | 76少妇精品导航 | 人妻体内射精一区二区三四 | 十八禁视频网站在线观看 | 成人无码精品1区2区3区免费看 | 日本欧美一区二区三区乱码 | 久久国产精品精品国产色婷婷 | 亚洲成av人片天堂网无码】 | 亚洲成av人在线观看网址 | 国内精品久久久久久中文字幕 | www国产亚洲精品久久网站 | 四十如虎的丰满熟妇啪啪 | 男女猛烈xx00免费视频试看 | 特大黑人娇小亚洲女 | 极品尤物被啪到呻吟喷水 | 国内少妇偷人精品视频 | 国产成人无码av片在线观看不卡 | 成人aaa片一区国产精品 | 人人澡人人妻人人爽人人蜜桃 | 亚洲中文无码av永久不收费 | 夜夜躁日日躁狠狠久久av | 久久久久99精品成人片 | 久久久久99精品成人片 | 精品久久久无码人妻字幂 | 荫蒂添的好舒服视频囗交 | 国产成人精品一区二区在线小狼 | 兔费看少妇性l交大片免费 | 九九在线中文字幕无码 | 久久亚洲日韩精品一区二区三区 | 久久亚洲中文字幕精品一区 | 国产区女主播在线观看 | 任你躁国产自任一区二区三区 | 蜜桃视频韩日免费播放 | 精品少妇爆乳无码av无码专区 | 亚洲综合在线一区二区三区 | 国产办公室秘书无码精品99 | 人人妻人人澡人人爽人人精品浪潮 | 狠狠亚洲超碰狼人久久 | 中文字幕乱码人妻无码久久 | 亚洲の无码国产の无码影院 | 精品少妇爆乳无码av无码专区 | 精品日本一区二区三区在线观看 | 亚洲综合无码久久精品综合 | 福利一区二区三区视频在线观看 | 国产办公室秘书无码精品99 | 麻豆国产97在线 | 欧洲 | 2020久久超碰国产精品最新 | www国产亚洲精品久久久日本 | 美女毛片一区二区三区四区 | 国产亚洲精品久久久闺蜜 | 中文精品无码中文字幕无码专区 | 亚洲熟妇自偷自拍另类 | 亚洲国产av精品一区二区蜜芽 | 少妇性l交大片 | 未满小14洗澡无码视频网站 | 国产精品99爱免费视频 | 国产午夜亚洲精品不卡下载 | 久久久久av无码免费网 | 欧洲精品码一区二区三区免费看 | 日本精品久久久久中文字幕 | 人妻aⅴ无码一区二区三区 | 国产后入清纯学生妹 | 亚洲日韩一区二区三区 | 精品一区二区三区无码免费视频 | 亚洲午夜久久久影院 | 日本一区二区更新不卡 | 精品少妇爆乳无码av无码专区 | 欧美丰满熟妇xxxx | 人妻中文无码久热丝袜 | 亚洲日韩乱码中文无码蜜桃臀网站 | 天海翼激烈高潮到腰振不止 | 国产高潮视频在线观看 | 国产舌乚八伦偷品w中 | 国产成人av免费观看 | 性生交大片免费看女人按摩摩 | 久久亚洲日韩精品一区二区三区 | 国精产品一区二区三区 | 熟女少妇在线视频播放 | 亚洲 欧美 激情 小说 另类 | 成人一在线视频日韩国产 | 波多野结衣高清一区二区三区 | 国产综合久久久久鬼色 | 国产精品无码一区二区三区不卡 | 欧美成人免费全部网站 | 两性色午夜视频免费播放 | 高清国产亚洲精品自在久久 | 国产两女互慰高潮视频在线观看 | 久久久久av无码免费网 | 亚洲成av人综合在线观看 | 国产亚洲精品久久久久久久久动漫 | 国内精品九九久久久精品 | 成在人线av无码免费 | 给我免费的视频在线观看 | 在线天堂新版最新版在线8 | 99久久人妻精品免费一区 | 欧美黑人巨大xxxxx | 大肉大捧一进一出好爽视频 | 少妇激情av一区二区 | 国产精品亚洲专区无码不卡 | 亚洲国产精品无码久久久久高潮 | 亚洲中文字幕久久无码 | 亚洲国产综合无码一区 | 天天躁夜夜躁狠狠是什么心态 | 东京热无码av男人的天堂 | 强开小婷嫩苞又嫩又紧视频 | 精品熟女少妇av免费观看 | 婷婷综合久久中文字幕蜜桃三电影 | v一区无码内射国产 | 少妇性l交大片欧洲热妇乱xxx | 欧美日韩一区二区综合 | 国内精品一区二区三区不卡 | 欧美丰满老熟妇xxxxx性 | 成人精品一区二区三区中文字幕 | 午夜免费福利小电影 | 久久久久99精品成人片 | 国产成人无码a区在线观看视频app | 狠狠综合久久久久综合网 | 婷婷色婷婷开心五月四房播播 | 国产亲子乱弄免费视频 | 草草网站影院白丝内射 | 女高中生第一次破苞av | 99久久亚洲精品无码毛片 | 日本va欧美va欧美va精品 | 日日干夜夜干 | 狠狠亚洲超碰狼人久久 | 日韩精品久久久肉伦网站 | 乱码av麻豆丝袜熟女系列 | 欧美日韩亚洲国产精品 | 永久黄网站色视频免费直播 | 久久久久免费看成人影片 | 国产无遮挡又黄又爽免费视频 | 十八禁视频网站在线观看 | 成人动漫在线观看 | 亚洲大尺度无码无码专区 | 人妻少妇精品无码专区动漫 | 亚洲日韩一区二区三区 | 人人妻人人澡人人爽人人精品 | 成人无码影片精品久久久 | 国产精品va在线观看无码 | 国产精品-区区久久久狼 | 欧美激情一区二区三区成人 | 又紧又大又爽精品一区二区 | 精品国产一区二区三区四区 | 成人一区二区免费视频 | 又大又紧又粉嫩18p少妇 | 强辱丰满人妻hd中文字幕 | 久久亚洲精品成人无码 | 亚洲成熟女人毛毛耸耸多 | 色诱久久久久综合网ywww | 日韩av无码中文无码电影 | 麻豆国产97在线 | 欧洲 | 久久精品无码一区二区三区 | 中文字幕人妻丝袜二区 | 国内精品人妻无码久久久影院蜜桃 | 国产精品亚洲一区二区三区喷水 | 99久久精品午夜一区二区 | 乱码av麻豆丝袜熟女系列 | 激情内射日本一区二区三区 | 无套内谢的新婚少妇国语播放 | 亚洲熟妇色xxxxx欧美老妇y | 中文毛片无遮挡高清免费 | 草草网站影院白丝内射 | 一本大道久久东京热无码av | 亚洲综合另类小说色区 | 国产精品久免费的黄网站 | 久久无码中文字幕免费影院蜜桃 | 亚洲の无码国产の无码影院 | 性做久久久久久久久 | 色综合久久中文娱乐网 | 精品国产一区二区三区四区 | 大肉大捧一进一出视频出来呀 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久综合九色综合97网 | 国产精品无码一区二区三区不卡 | 国产成人精品一区二区在线小狼 | 亚洲乱亚洲乱妇50p | 大地资源中文第3页 | 无码毛片视频一区二区本码 | 亚洲乱码中文字幕在线 | 激情爆乳一区二区三区 | 久久精品无码一区二区三区 | 在教室伦流澡到高潮hnp视频 | 国产精品亚洲а∨无码播放麻豆 | √8天堂资源地址中文在线 | 红桃av一区二区三区在线无码av | 小泽玛莉亚一区二区视频在线 | 日韩精品一区二区av在线 | 曰韩无码二三区中文字幕 | 免费人成在线观看网站 | 熟妇人妻无乱码中文字幕 | 又大又黄又粗又爽的免费视频 | 国产综合久久久久鬼色 | 精品无码一区二区三区爱欲 | 精品久久综合1区2区3区激情 | 国产三级精品三级男人的天堂 | 狠狠亚洲超碰狼人久久 | 自拍偷自拍亚洲精品被多人伦好爽 | 风流少妇按摩来高潮 | 国产真实乱对白精彩久久 | 亚洲日韩精品欧美一区二区 | 98国产精品综合一区二区三区 | 国产精品久久福利网站 | 精品国产一区二区三区av 性色 | ass日本丰满熟妇pics | 99麻豆久久久国产精品免费 | 少妇人妻偷人精品无码视频 | 蜜桃无码一区二区三区 | 日韩欧美中文字幕公布 | 国产麻豆精品精东影业av网站 | 精品久久久无码人妻字幂 | 国产精品久久久久影院嫩草 | 亚洲熟妇色xxxxx欧美老妇 | 国产人妻人伦精品1国产丝袜 | 曰韩少妇内射免费播放 | 无码av免费一区二区三区试看 | 精品熟女少妇av免费观看 | 18黄暴禁片在线观看 | 亚洲热妇无码av在线播放 | 免费乱码人妻系列无码专区 | 乌克兰少妇性做爰 | 欧美激情内射喷水高潮 | 蜜桃av抽搐高潮一区二区 | 欧美人与善在线com | 青春草在线视频免费观看 | 国产欧美熟妇另类久久久 | 国产乱码精品一品二品 | 亚洲а∨天堂久久精品2021 | 免费观看的无遮挡av | 亚洲国产精品一区二区美利坚 | 国产成人无码区免费内射一片色欲 | 婷婷色婷婷开心五月四房播播 | 小泽玛莉亚一区二区视频在线 | 国内揄拍国内精品少妇国语 | 内射老妇bbwx0c0ck | 亚洲一区二区观看播放 | 亚洲 另类 在线 欧美 制服 | 日韩欧美群交p片內射中文 | 免费观看激色视频网站 | 在线播放免费人成毛片乱码 | 亚洲欧美中文字幕5发布 | 亚洲色欲久久久综合网东京热 | 丰满人妻精品国产99aⅴ | 成 人 网 站国产免费观看 | 欧美日本免费一区二区三区 | 国产精品人人爽人人做我的可爱 | 日韩欧美中文字幕公布 | 内射爽无广熟女亚洲 | 国内揄拍国内精品人妻 | 国内精品一区二区三区不卡 | 丰满妇女强制高潮18xxxx | 午夜熟女插插xx免费视频 | 久久无码人妻影院 | 网友自拍区视频精品 | 成人精品视频一区二区 | 亚洲爆乳大丰满无码专区 | 亚洲色成人中文字幕网站 | 午夜精品一区二区三区在线观看 | 亚洲人亚洲人成电影网站色 | 青春草在线视频免费观看 | 久久99精品国产麻豆蜜芽 | 熟女体下毛毛黑森林 | 性生交大片免费看l | 国产特级毛片aaaaaa高潮流水 | 狂野欧美性猛xxxx乱大交 | 波多野结衣av一区二区全免费观看 | 国产内射爽爽大片视频社区在线 | 黑森林福利视频导航 | 双乳奶水饱满少妇呻吟 | 婷婷六月久久综合丁香 | 欧美丰满少妇xxxx性 | 一区二区传媒有限公司 | 日本丰满熟妇videos | 婷婷六月久久综合丁香 | 日本大乳高潮视频在线观看 | 亚洲中文字幕无码中文字在线 | 精品久久久中文字幕人妻 | 76少妇精品导航 | 国产精品第一国产精品 | 国产精品毛多多水多 | 99久久婷婷国产综合精品青草免费 | 亚洲第一网站男人都懂 | 亚洲欧洲无卡二区视頻 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 女人被爽到呻吟gif动态图视看 | 精品国偷自产在线 | 欧洲欧美人成视频在线 | 天天躁日日躁狠狠躁免费麻豆 | 99久久婷婷国产综合精品青草免费 | 日韩精品无码一区二区中文字幕 | 欧美黑人巨大xxxxx | 亚洲欧美色中文字幕在线 | аⅴ资源天堂资源库在线 | 少妇厨房愉情理9仑片视频 | 日韩欧美中文字幕公布 | 亚洲国产欧美国产综合一区 | 狂野欧美性猛xxxx乱大交 | 无码帝国www无码专区色综合 | 色五月丁香五月综合五月 | 欧美成人免费全部网站 | 亚洲成av人在线观看网址 | 国产精品久久久久无码av色戒 | 久久国产精品萌白酱免费 | 国产激情无码一区二区 | 久久久精品成人免费观看 | 国产亚洲精品久久久闺蜜 | 日韩欧美中文字幕在线三区 | 真人与拘做受免费视频一 | 国产人妻精品一区二区三区不卡 | 特级做a爰片毛片免费69 | 久久国语露脸国产精品电影 | 亚洲男女内射在线播放 | 亚洲午夜久久久影院 | 久久久久久av无码免费看大片 | 西西人体www44rt大胆高清 | 图片区 小说区 区 亚洲五月 | 夜精品a片一区二区三区无码白浆 | 露脸叫床粗话东北少妇 | 2020久久超碰国产精品最新 | 久久久久免费精品国产 | 国产精品爱久久久久久久 | 国产肉丝袜在线观看 | 日本va欧美va欧美va精品 | 色综合久久中文娱乐网 | 亚洲国产精品一区二区美利坚 | 人妻天天爽夜夜爽一区二区 | 国产成人精品一区二区在线小狼 | 无套内谢的新婚少妇国语播放 | 精品人妻人人做人人爽夜夜爽 | 成人性做爰aaa片免费看不忠 | 99精品无人区乱码1区2区3区 | 亚洲精品国产精品乱码不卡 | 四虎国产精品一区二区 | 女人被爽到呻吟gif动态图视看 | 成人影院yy111111在线观看 | 久久99精品久久久久婷婷 | 国产成人精品优优av | 无码一区二区三区在线观看 | 日本精品久久久久中文字幕 | 正在播放老肥熟妇露脸 | 少妇一晚三次一区二区三区 | 国产激情综合五月久久 | 亚洲国产av精品一区二区蜜芽 | 国产人妻人伦精品1国产丝袜 | 国产成人精品优优av | 国产精品亚洲lv粉色 | 男人的天堂2018无码 | 亚洲一区二区三区偷拍女厕 | 国产午夜手机精彩视频 | 久久五月精品中文字幕 | www一区二区www免费 | 色情久久久av熟女人妻网站 | 久久国产自偷自偷免费一区调 | 亚洲国精产品一二二线 | 天天躁夜夜躁狠狠是什么心态 | 国产午夜福利亚洲第一 | 亚洲国产欧美国产综合一区 | 国产成人一区二区三区在线观看 | 成人亚洲精品久久久久软件 | 水蜜桃色314在线观看 | 97精品国产97久久久久久免费 | 国产精品亚洲综合色区韩国 | 国产人成高清在线视频99最全资源 | 成人性做爰aaa片免费看不忠 | 久久99精品久久久久婷婷 | 国产口爆吞精在线视频 | 亚洲综合久久一区二区 | 少妇被粗大的猛进出69影院 | 一本大道久久东京热无码av | 无码人妻精品一区二区三区不卡 | 荫蒂被男人添的好舒服爽免费视频 | 成人三级无码视频在线观看 | 人妻天天爽夜夜爽一区二区 | 久久天天躁狠狠躁夜夜免费观看 | 久久综合九色综合欧美狠狠 | 男女性色大片免费网站 | 天天摸天天碰天天添 | 国产熟妇高潮叫床视频播放 | 中文亚洲成a人片在线观看 | 欧美阿v高清资源不卡在线播放 | 国产网红无码精品视频 | 中文字幕乱码中文乱码51精品 | 久久综合狠狠综合久久综合88 | 3d动漫精品啪啪一区二区中 | 大地资源网第二页免费观看 | 在线观看免费人成视频 | 亚洲最大成人网站 | 国产一区二区三区日韩精品 | 国产成人综合在线女婷五月99播放 | 日韩人妻少妇一区二区三区 | 国产成人精品无码播放 | 性色av无码免费一区二区三区 | 国产精品无码一区二区三区不卡 | 爽爽影院免费观看 | 精品国产一区二区三区四区 | 好屌草这里只有精品 | 我要看www免费看插插视频 | 撕开奶罩揉吮奶头视频 | 少妇被黑人到高潮喷出白浆 | 天堂а√在线地址中文在线 | 欧美freesex黑人又粗又大 | 免费国产黄网站在线观看 | 亚洲阿v天堂在线 | 亚洲成a人片在线观看无码 | 精品乱子伦一区二区三区 | 强奷人妻日本中文字幕 | 一个人免费观看的www视频 | 300部国产真实乱 | 亚洲乱亚洲乱妇50p | 亚洲欧美日韩成人高清在线一区 | 亚洲一区二区三区含羞草 | 国产激情精品一区二区三区 | 野狼第一精品社区 | 亚洲乱码中文字幕在线 | 无码吃奶揉捏奶头高潮视频 | 1000部啪啪未满十八勿入下载 | 撕开奶罩揉吮奶头视频 | 国产无遮挡又黄又爽免费视频 | 真人与拘做受免费视频 | 无码国产色欲xxxxx视频 | 在线观看国产午夜福利片 | 亚拍精品一区二区三区探花 | 久久久久av无码免费网 | 在线精品国产一区二区三区 | 国产精品人人爽人人做我的可爱 | 正在播放老肥熟妇露脸 | 国产精品香蕉在线观看 | 天天做天天爱天天爽综合网 | 亚洲熟妇色xxxxx亚洲 | 午夜福利电影 | 未满小14洗澡无码视频网站 | www成人国产高清内射 | 免费无码肉片在线观看 | 人妻少妇精品久久 | 无码人妻丰满熟妇区五十路百度 | 国产成人午夜福利在线播放 | 人妻互换免费中文字幕 | 最近中文2019字幕第二页 | 亚洲小说图区综合在线 | 久久国产精品偷任你爽任你 | 亚洲中文字幕无码中文字在线 | 国产乱子伦视频在线播放 | 一本一道久久综合久久 | 一本色道久久综合狠狠躁 | 骚片av蜜桃精品一区 | 日本www一道久久久免费榴莲 | 亚洲一区二区三区香蕉 | 一本久久伊人热热精品中文字幕 | 国产av一区二区三区最新精品 | www成人国产高清内射 | 亚洲精品国产精品乱码不卡 | 西西人体www44rt大胆高清 | 精品久久8x国产免费观看 | 又紧又大又爽精品一区二区 | 久久午夜无码鲁丝片 | 永久免费观看美女裸体的网站 | 麻花豆传媒剧国产免费mv在线 | av无码不卡在线观看免费 | 成人一区二区免费视频 | 少妇性l交大片欧洲热妇乱xxx | 成在人线av无码免观看麻豆 | 久久99精品久久久久久 | 亚洲欧美日韩成人高清在线一区 | 国产美女极度色诱视频www | 国产亚洲精品久久久ai换 | 在线看片无码永久免费视频 | 少妇高潮喷潮久久久影院 | 欧美第一黄网免费网站 | 97久久国产亚洲精品超碰热 | 中文字幕日产无线码一区 | 97久久超碰中文字幕 | 中文久久乱码一区二区 | 久久亚洲中文字幕无码 | 亚洲自偷精品视频自拍 | 久久综合九色综合欧美狠狠 | 日韩欧美中文字幕公布 | 国产猛烈高潮尖叫视频免费 | 色婷婷av一区二区三区之红樱桃 | 中文字幕无码av激情不卡 | 波多野结衣乳巨码无在线观看 | 日韩欧美中文字幕公布 | 永久免费观看美女裸体的网站 | 最近的中文字幕在线看视频 | 亚洲日本一区二区三区在线 | 丰满人妻一区二区三区免费视频 | 国内精品九九久久久精品 | 国产特级毛片aaaaaa高潮流水 | 欧美人与动性行为视频 | 亚洲国产欧美在线成人 | 亚洲色在线无码国产精品不卡 | 日本精品少妇一区二区三区 | 国产舌乚八伦偷品w中 | 国产美女精品一区二区三区 | 国产精品久久久久久无码 | 国产精品高潮呻吟av久久 | 国产成人无码av片在线观看不卡 | 亚洲国产精品无码一区二区三区 | 99视频精品全部免费免费观看 | 国产一区二区三区精品视频 | 国产黄在线观看免费观看不卡 | 老头边吃奶边弄进去呻吟 | 色婷婷香蕉在线一区二区 | 成人试看120秒体验区 | 精品久久8x国产免费观看 | 亚洲天堂2017无码中文 | 18精品久久久无码午夜福利 | 久久久久人妻一区精品色欧美 | 亚洲日韩av一区二区三区中文 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲成色www久久网站 | 久久www免费人成人片 | 福利一区二区三区视频在线观看 | 性欧美牲交在线视频 | 中文字幕精品av一区二区五区 | 精品人妻人人做人人爽夜夜爽 | 九九热爱视频精品 | 娇妻被黑人粗大高潮白浆 | 在线播放免费人成毛片乱码 | 99久久久无码国产aaa精品 | 亚洲娇小与黑人巨大交 | 亚洲爆乳无码专区 | 国内精品人妻无码久久久影院 | 四虎国产精品免费久久 | 欧美午夜特黄aaaaaa片 | 国产人妻精品一区二区三区 | 日本护士毛茸茸高潮 | 乌克兰少妇xxxx做受 | 超碰97人人做人人爱少妇 | 国产97在线 | 亚洲 | av无码久久久久不卡免费网站 | 久久综合给合久久狠狠狠97色 | 中文字幕乱码人妻二区三区 | 人人超人人超碰超国产 | 欧美肥老太牲交大战 | 无码中文字幕色专区 | 蜜桃臀无码内射一区二区三区 | 免费观看又污又黄的网站 | 亚洲日韩中文字幕在线播放 | 亚洲成色www久久网站 | 国产人妻大战黑人第1集 | 国产熟妇高潮叫床视频播放 | 131美女爱做视频 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久99精品国产.久久久久 | 久久久久久久人妻无码中文字幕爆 | 成人无码精品1区2区3区免费看 | 亚洲午夜久久久影院 | 午夜精品久久久久久久 | 欧美一区二区三区视频在线观看 | 日韩人妻无码一区二区三区久久99 | 久久伊人色av天堂九九小黄鸭 | 丰满岳乱妇在线观看中字无码 | 对白脏话肉麻粗话av | 亚洲伊人久久精品影院 | 日韩精品无码一区二区中文字幕 | 国产综合久久久久鬼色 | 久久无码中文字幕免费影院蜜桃 | 精品久久久久久亚洲精品 | 久久综合九色综合欧美狠狠 | 人人妻人人澡人人爽人人精品浪潮 | 久久久婷婷五月亚洲97号色 | 欧美自拍另类欧美综合图片区 | 精品成在人线av无码免费看 | 欧美丰满老熟妇xxxxx性 | 色婷婷av一区二区三区之红樱桃 | 激情内射日本一区二区三区 | www国产亚洲精品久久久日本 | 国产婷婷色一区二区三区在线 | 久久婷婷五月综合色国产香蕉 | 又色又爽又黄的美女裸体网站 | 亚洲aⅴ无码成人网站国产app | 爱做久久久久久 | 日韩精品a片一区二区三区妖精 | 无码国产乱人伦偷精品视频 | 久久国产自偷自偷免费一区调 | 5858s亚洲色大成网站www | 国产av人人夜夜澡人人爽麻豆 | 亚洲小说图区综合在线 | 成人女人看片免费视频放人 | 成人无码视频在线观看网站 | 2020久久香蕉国产线看观看 | 国产亚洲精品久久久闺蜜 | 亚洲精品欧美二区三区中文字幕 | 国产精品国产自线拍免费软件 | 亚洲а∨天堂久久精品2021 | 色综合久久久久综合一本到桃花网 | 国产精品人人爽人人做我的可爱 | 午夜精品久久久久久久 | 午夜精品久久久久久久 | 在线а√天堂中文官网 | 久久久精品人妻久久影视 | 国产成人久久精品流白浆 | 久久zyz资源站无码中文动漫 | 国产在线精品一区二区高清不卡 | 人妻体内射精一区二区三四 | 免费人成在线观看网站 | www国产亚洲精品久久网站 | 国产激情综合五月久久 | 男女性色大片免费网站 | 99riav国产精品视频 | 国产性生交xxxxx无码 | 亚洲 欧美 激情 小说 另类 | 牲欲强的熟妇农村老妇女视频 | 丰满人妻精品国产99aⅴ | 精品欧美一区二区三区久久久 | 久久久久久久女国产乱让韩 | 永久免费观看国产裸体美女 | 欧美日韩亚洲国产精品 | 日本www一道久久久免费榴莲 | 亚洲成av人影院在线观看 | 免费视频欧美无人区码 | 亚洲国产精品成人久久蜜臀 | 国产亚洲精品久久久久久大师 | 久久久中文字幕日本无吗 | 青青草原综合久久大伊人精品 | 少妇性l交大片欧洲热妇乱xxx | 全黄性性激高免费视频 | 亚洲色偷偷男人的天堂 | 免费观看激色视频网站 | 亚洲色偷偷男人的天堂 | 久久天天躁狠狠躁夜夜免费观看 | 99久久精品国产一区二区蜜芽 | 精品国产乱码久久久久乱码 | 精品国精品国产自在久国产87 | 色狠狠av一区二区三区 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 性色欲网站人妻丰满中文久久不卡 | 亚洲欧洲日本综合aⅴ在线 | 美女扒开屁股让男人桶 | 亚洲第一网站男人都懂 | 无码一区二区三区在线 | 中文字幕日产无线码一区 | 中文精品无码中文字幕无码专区 | 无遮挡啪啪摇乳动态图 | 国产午夜精品一区二区三区嫩草 |