日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

【转】Java Socket编程基础及深入讲解

發(fā)布時(shí)間:2023/11/30 java 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】Java Socket编程基础及深入讲解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文:https://www.cnblogs.com/yiwangzhibujian/p/7107785.html#q2.3.3

Socket是Java網(wǎng)絡(luò)編程的基礎(chǔ),了解還是有好處的,

  這篇文章主要講解Socket的基礎(chǔ)編程。Socket用在哪呢,主要用在進(jìn)程間,網(wǎng)絡(luò)間通信。本篇比較長,特別做了個(gè)目錄:

一、Socket通信基本示例

二、消息通信優(yōu)化

    • 2.1 雙向通信,發(fā)送消息并接受消息
    • 2.2 使用場景
    • 2.3 如何告知對(duì)方已發(fā)送完命令
      • 2.3.1 通過Socket關(guān)閉
      • 2.3.2 通過Socket關(guān)閉輸出流的方式
      • 2.3.3 通過約定符號(hào)
      • 2.3.4 通過指定長度

三、服務(wù)端優(yōu)化

    • 3.1 服務(wù)端并發(fā)處理能力
    • 3.2 服務(wù)端其他屬性
    • 3.3 性能再次提升

四、Socket的其它知識(shí)

    • 4.1 客戶端綁定端口
    • 4.2 讀超時(shí)SO_TIMEOUT
    • 4.3 設(shè)置連接超時(shí)
    • 4.4 判斷Socket是否可用
      • 4.4.1 自定義心跳包
      • 4.4.2 通過發(fā)送緊急數(shù)據(jù)
      • 4.4.3 真的需要判斷連接斷開嗎
    • 4.5 設(shè)置端口重用SO_REUSEADDR?
    • 4.6 設(shè)置關(guān)閉等待SO_LINGER
    • 4.7 設(shè)置發(fā)送延遲策略TCP_NODELAY
    • 4.8 設(shè)置輸出輸出緩沖區(qū)大小SO_RCVBUF/SO_SNDBUF
    • 4.9 設(shè)置保持連接存活SO_KEEPALIVE
    • 4.10 異常:java.net.SocketException: Connection reset by peer

五、關(guān)于Socket的理解

    • 5.1 Socket和TCP/IP
    • 5.2 Socket和RMI
    • 5.3 DatagramSocket與Socket
    • 5.4 拆包和黏包
      • 5.4.1 黏包
      • 5.4.2 拆包

一、Socket通信基本示例

  這種模式是基礎(chǔ),必須掌握,后期對(duì)Socket的優(yōu)化都是在這個(gè)基礎(chǔ)上的,也是為以后學(xué)習(xí)NIO做鋪墊。

package yiwangzhibujian.onlysend;import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;public class SocketServer {public static void main(String[] args) throws Exception {// 監(jiān)聽指定的端口int port = 55533;ServerSocket server = new ServerSocket(port);// server將一直等待連接的到來System.out.println("server將一直等待連接的到來");Socket socket = server.accept();// 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();while ((len = inputStream.read(bytes)) != -1) {//注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(new String(bytes, 0, len,"UTF-8"));}System.out.println("get message from client: " + sb);inputStream.close();socket.close();server.close();} }

  服務(wù)端監(jiān)聽一個(gè)端口,等待連接的到來。

package yiwangzhibujian.onlysend;import java.io.OutputStream; import java.net.Socket;public class SocketClient {public static void main(String args[]) throws Exception {// 要連接的服務(wù)端IP地址和端口String host = "127.0.0.1"; int port = 55533;// 與服務(wù)端建立連接Socket socket = new Socket(host, port);// 建立連接后獲得輸出流OutputStream outputStream = socket.getOutputStream();String message="你好 yiwangzhibujian";socket.getOutputStream().write(message.getBytes("UTF-8"));outputStream.close();socket.close();} }

  客戶端通過ip和端口,連接到指定的server,然后通過Socket獲得輸出流,并向其輸出內(nèi)容,服務(wù)器會(huì)獲得消息。最終服務(wù)端控制臺(tái)打印如下:

server將一直等待連接的到來 get message from client: 你好 yiwangzhibujian

  通過這個(gè)例子應(yīng)該掌握并了解:

  • Socket服務(wù)端和客戶端的基本編程
  • 傳輸編碼統(tǒng)一指定,防止亂碼

  這個(gè)例子做為學(xué)習(xí)的基本例子,實(shí)際開發(fā)中會(huì)有各種變形,比如客戶端在發(fā)送完消息后,需要服務(wù)端進(jìn)行處理并返回,如下。

二、消息通信優(yōu)化

2.1 雙向通信,發(fā)送消息并接受消息

  這個(gè)也是做為Socket編程的基本,應(yīng)該掌握,例子如下:

package yiwangzhibujian.waitreceive;import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;public class SocketServer {public static void main(String[] args) throws Exception {// 監(jiān)聽指定的端口int port = 55533;ServerSocket server = new ServerSocket(port);// server將一直等待連接的到來System.out.println("server將一直等待連接的到來");Socket socket = server.accept();// 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();//只有當(dāng)客戶端關(guān)閉它的輸出流的時(shí)候,服務(wù)端才能取得結(jié)尾的-1while ((len = inputStream.read(bytes)) != -1) {// 注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(new String(bytes, 0, len, "UTF-8"));}System.out.println("get message from client: " + sb);OutputStream outputStream = socket.getOutputStream();outputStream.write("Hello Client,I get the message.".getBytes("UTF-8"));inputStream.close();outputStream.close();socket.close();server.close();} }

  與之前server的不同在于,當(dāng)讀取完客戶端的消息后,打開輸出流,將指定消息發(fā)送回客戶端,客戶端程序?yàn)?#xff1a;

package yiwangzhibujian.waitreceive;import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;public class SocketClient {public static void main(String args[]) throws Exception {// 要連接的服務(wù)端IP地址和端口String host = "127.0.0.1";int port = 55533;// 與服務(wù)端建立連接Socket socket = new Socket(host, port);// 建立連接后獲得輸出流OutputStream outputStream = socket.getOutputStream();String message = "你好 yiwangzhibujian";socket.getOutputStream().write(message.getBytes("UTF-8"));//通過shutdownOutput高速服務(wù)器已經(jīng)發(fā)送完數(shù)據(jù),后續(xù)只能接受數(shù)據(jù)socket.shutdownOutput();InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();while ((len = inputStream.read(bytes)) != -1) {//注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(new String(bytes, 0, len,"UTF-8"));}System.out.println("get message from server: " + sb);inputStream.close();outputStream.close();socket.close();} }

  客戶端也有相應(yīng)的變化,在發(fā)送完消息時(shí),調(diào)用關(guān)閉輸出流方法,然后打開輸出流,等候服務(wù)端的消息。

2.2 使用場景

  這個(gè)模式的使用場景一般用在,客戶端發(fā)送命令給服務(wù)器,然后服務(wù)器相應(yīng)指定的命令,如果只是客戶端發(fā)送消息給服務(wù)器,然后讓服務(wù)器返回收到消息的消息,這就有點(diǎn)過分了,這就是完全不相信Socket的傳輸安全性,要知道它的底層可是TCP,如果沒有發(fā)送到服務(wù)器端是會(huì)拋異常的,這點(diǎn)完全不用擔(dān)心。

2.3 如何告知對(duì)方已發(fā)送完命令

  其實(shí)這個(gè)問題還是比較重要的,正常來說,客戶端打開一個(gè)輸出流,如果不做約定,也不關(guān)閉它,那么服務(wù)端永遠(yuǎn)不知道客戶端是否發(fā)送完消息,那么服務(wù)端會(huì)一直等待下去,直到讀取超時(shí)。所以怎么告知服務(wù)端已經(jīng)發(fā)送完消息就顯得特別重要。

2.3.1 通過Socket關(guān)閉

  這個(gè)是第一章介紹的方式,當(dāng)Socket關(guān)閉的時(shí)候,服務(wù)端就會(huì)收到響應(yīng)的關(guān)閉信號(hào),那么服務(wù)端也就知道流已經(jīng)關(guān)閉了,這個(gè)時(shí)候讀取操作完成,就可以繼續(xù)后續(xù)工作。

  但是這種方式有一些缺點(diǎn)

  • 客戶端Socket關(guān)閉后,將不能接受服務(wù)端發(fā)送的消息,也不能再次發(fā)送消息
  • 如果客戶端想再次發(fā)送消息,需要重現(xiàn)創(chuàng)建Socket連接

2.3.2 通過Socket關(guān)閉輸出流的方式

  這種方式調(diào)用的方法是:

socket.shutdownOutput();

  而不是(outputStream為發(fā)送消息到服務(wù)端打開的輸出流):

outputStream.close();

  如果關(guān)閉了輸出流,那么相應(yīng)的Socket也將關(guān)閉,和直接關(guān)閉Socket一個(gè)性質(zhì)。

  調(diào)用Socket的shutdownOutput()方法,底層會(huì)告知服務(wù)端我這邊已經(jīng)寫完了,那么服務(wù)端收到消息后,就能知道已經(jīng)讀取完消息,如果服務(wù)端有要返回給客戶的消息那么就可以通過服務(wù)端的輸出流發(fā)送給客戶端,如果沒有,直接關(guān)閉Socket。

  這種方式通過關(guān)閉客戶端的輸出流,告知服務(wù)端已經(jīng)寫完了,雖然可以讀到服務(wù)端發(fā)送的消息,但是還是有一點(diǎn)點(diǎn)缺點(diǎn):

  • 不能再次發(fā)送消息給服務(wù)端,如果再次發(fā)送,需要重新建立Socket連接

  這個(gè)缺點(diǎn),在訪問頻率比較高的情況下將是一個(gè)需要優(yōu)化的地方。

2.3.3 通過約定符號(hào)

  這種方式的用法,就是雙方約定一個(gè)字符或者一個(gè)短語,來當(dāng)做消息發(fā)送完成的標(biāo)識(shí),通常這么做就需要改造讀取方法。

  假如約定單端的一行為end,代表發(fā)送完成,例如下面的消息,end則代表消息發(fā)送完成:

hello yiwangzhibujian end

  那么服務(wù)端響應(yīng)的讀取操作需要進(jìn)行如下改造:

Socket socket = server.accept(); // 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取 BufferedReader read=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")); String line; StringBuilder sb = new StringBuilder(); while ((line = read.readLine()) != null && "end".equals(line)) {//注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(line); }

  可以看見,服務(wù)端不僅判斷是否讀到了流的末尾,還判斷了是否讀到了約定的末尾。

  這么做的優(yōu)缺點(diǎn)如下:

  • 優(yōu)點(diǎn):不需要關(guān)閉流,當(dāng)發(fā)送完一條命令(消息)后可以再次發(fā)送新的命令(消息)
  • 缺點(diǎn):需要額外的約定結(jié)束標(biāo)志,太簡單的容易出現(xiàn)在要發(fā)送的消息中,誤被結(jié)束,太復(fù)雜的不好處理,還占帶寬

  經(jīng)過了這么多的優(yōu)化還是有缺點(diǎn),難道就沒有完美的解決方案嗎,答案是有的,看接下來的內(nèi)容。

2.3.4 通過指定長度

  如果你了解一點(diǎn)class文件的結(jié)構(gòu)(后續(xù)會(huì)寫,敬請(qǐng)期待),那么你就會(huì)佩服這么設(shè)計(jì)方式,也就是說我們可以在此找靈感,就是我們可以先指定后續(xù)命令的長度,然后讀取指定長度的內(nèi)容做為客戶端發(fā)送的消息。

  現(xiàn)在首要的問題就是用幾個(gè)字節(jié)指定長度呢,我們可以算一算:

  • 1個(gè)字節(jié):最大256,表示256B
  • 2個(gè)字節(jié):最大65536,表示64K
  • 3個(gè)字節(jié):最大16777216,表示16M
  • 4個(gè)字節(jié):最大4294967296,表示4G
  • 依次類推

  這個(gè)時(shí)候是不是很糾結(jié),最大的當(dāng)然是最保險(xiǎn)的,但是真的有必要選擇最大的嗎,其實(shí)如果你稍微了解一點(diǎn)UTF-8的編碼方式(字符編碼后續(xù)會(huì)寫,敬請(qǐng)期待),那么你就應(yīng)該能想到為什么一定要固定表示長度字節(jié)的長度呢,我們可以使用變長方式來表示長度的表示,比如:

  • 第一個(gè)字節(jié)首位為0:即0XXXXXXX,表示長度就一個(gè)字節(jié),最大128,表示128B
  • 第一個(gè)字節(jié)首位為110,那么附帶后面一個(gè)字節(jié)表示長度:即110XXXXX?10XXXXXX,最大2048,表示2K
  • 第一個(gè)字節(jié)首位為1110,那么附帶后面二個(gè)字節(jié)表示長度:即110XXXXX?10XXXXXX?10XXXXXX,最大131072,表示128K
  • 依次類推

  上面提到的這種用法適合高富帥的程序員使用,一般呢,如果用作命名發(fā)送,兩個(gè)字節(jié)就夠了,如果還不放心4個(gè)字節(jié)基本就能滿足你的所有要求,下面的例子我們將采用2個(gè)字節(jié)表示長度,目的只是給你一種思路,讓你知道有這種方式來獲取消息的結(jié)尾:

  服務(wù)端程序:

package yiwangzhibujian.waitreceive2;import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;public class SocketServer {public static void main(String[] args) throws Exception {// 監(jiān)聽指定的端口int port = 55533;ServerSocket server = new ServerSocket(port);// server將一直等待連接的到來System.out.println("server將一直等待連接的到來");Socket socket = server.accept();// 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取InputStream inputStream = socket.getInputStream();byte[] bytes;// 因?yàn)榭梢詮?fù)用Socket且能判斷長度,所以可以一個(gè)Socket用到底while (true) {// 首先讀取兩個(gè)字節(jié)表示的長度int first = inputStream.read();//如果讀取的值為-1 說明到了流的末尾,Socket已經(jīng)被關(guān)閉了,此時(shí)將不能再去讀取if(first==-1){break;}int second = inputStream.read();int length = (first << 8) + second;// 然后構(gòu)造一個(gè)指定長的byte數(shù)組bytes = new byte[length];// 然后讀取指定長度的消息即可inputStream.read(bytes);System.out.println("get message from client: " + new String(bytes, "UTF-8"));}inputStream.close();socket.close();server.close();} }

  此處的讀取步驟為,先讀取兩個(gè)字節(jié)的長度,然后讀取消息,客戶端為:

package yiwangzhibujian.waitreceive2;import java.io.OutputStream; import java.net.Socket;public class SocketClient {public static void main(String args[]) throws Exception {// 要連接的服務(wù)端IP地址和端口String host = "127.0.0.1";int port = 55533;// 與服務(wù)端建立連接Socket socket = new Socket(host, port);// 建立連接后獲得輸出流OutputStream outputStream = socket.getOutputStream();String message = "你好 yiwangzhibujian";//首先需要計(jì)算得知消息的長度byte[] sendBytes = message.getBytes("UTF-8");//然后將消息的長度優(yōu)先發(fā)送出去outputStream.write(sendBytes.length >>8);outputStream.write(sendBytes.length);//然后將消息再次發(fā)送出去outputStream.write(sendBytes);outputStream.flush();//==========此處重復(fù)發(fā)送一次,實(shí)際項(xiàng)目中為多個(gè)命名,此處只為展示用法message = "第二條消息";sendBytes = message.getBytes("UTF-8");outputStream.write(sendBytes.length >>8);outputStream.write(sendBytes.length);outputStream.write(sendBytes);outputStream.flush();//==========此處重復(fù)發(fā)送一次,實(shí)際項(xiàng)目中為多個(gè)命名,此處只為展示用法message = "the third message!";sendBytes = message.getBytes("UTF-8");outputStream.write(sendBytes.length >>8);outputStream.write(sendBytes.length);outputStream.write(sendBytes); outputStream.close();socket.close();} }

  客戶端要多做的是,在發(fā)送消息之前先把消息的長度發(fā)送過去。

  這種事先約定好長度的做法解決了之前提到的種種問題,Redis的Java客戶端Jedis就是用這種方式實(shí)現(xiàn)的這種方式的缺點(diǎn):

  • 暫時(shí)還沒發(fā)現(xiàn)

  當(dāng)然如果是需要服務(wù)器返回結(jié)果,那么也依然使用這種方式,服務(wù)端也是先發(fā)送結(jié)果的長度,然后客戶端進(jìn)行讀取。當(dāng)然現(xiàn)在流行的就是,長度+類型+數(shù)據(jù)模式的傳輸方式。

三、服務(wù)端優(yōu)化

3.1 服務(wù)端并發(fā)處理能力

  在上面的例子中,服務(wù)端僅僅只是接受了一個(gè)Socket請(qǐng)求,并處理了它,然后就結(jié)束了,但是在實(shí)際開發(fā)中,一個(gè)Socket服務(wù)往往需要服務(wù)大量的Socket請(qǐng)求,那么就不能再服務(wù)完一個(gè)Socket的時(shí)候就關(guān)閉了,這時(shí)候可以采用循環(huán)接受請(qǐng)求并處理的邏輯:

package yiwangzhibujian.multiserver;import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;public class SocketServer {public static void main(String args[]) throws IOException {// 監(jiān)聽指定的端口int port = 55533;ServerSocket server = new ServerSocket(port);// server將一直等待連接的到來System.out.println("server將一直等待連接的到來");while(true){Socket socket = server.accept();// 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();while ((len = inputStream.read(bytes)) != -1) {// 注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(new String(bytes, 0, len, "UTF-8"));}System.out.println("get message from client: " + sb);inputStream.close();socket.close();}} }

  這種一般也是新手寫法,但是能夠循環(huán)處理多個(gè)Socket請(qǐng)求,不過當(dāng)一個(gè)請(qǐng)求的處理比較耗時(shí)的時(shí)候,后面的請(qǐng)求將被阻塞,所以一般都是用多線程的方式來處理Socket,即每有一個(gè)Socket請(qǐng)求的時(shí)候,就創(chuàng)建一個(gè)線程來處理它。

  不過在實(shí)際生產(chǎn)中,創(chuàng)建的線程會(huì)交給線程池來處理,為了:

  • 線程復(fù)用,創(chuàng)建線程耗時(shí),回收線程慢
  • 防止短時(shí)間內(nèi)高并發(fā),指定線程池大小,超過數(shù)量將等待,方式短時(shí)間創(chuàng)建大量線程導(dǎo)致資源耗盡,服務(wù)掛掉
package yiwangzhibujian.threadserver;import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class SocketServer {public static void main(String args[]) throws Exception {// 監(jiān)聽指定的端口int port = 55533;ServerSocket server = new ServerSocket(port);// server將一直等待連接的到來System.out.println("server將一直等待連接的到來");//如果使用多線程,那就需要線程池,防止并發(fā)過高時(shí)創(chuàng)建過多線程耗盡資源ExecutorService threadPool = Executors.newFixedThreadPool(100);while (true) {Socket socket = server.accept();Runnable runnable=()->{try {// 建立好連接后,從socket中獲取輸入流,并建立緩沖區(qū)進(jìn)行讀取InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();while ((len = inputStream.read(bytes)) != -1) {// 注意指定編碼格式,發(fā)送方和接收方一定要統(tǒng)一,建議使用UTF-8sb.append(new String(bytes, 0, len, "UTF-8"));}System.out.println("get message from client: " + sb);inputStream.close();socket.close();} catch (Exception e) {e.printStackTrace();}};threadPool.submit(runnable);}} }

  使用線程池的方式,算是一種成熟的方式。可以應(yīng)用在生產(chǎn)中。

3.2 服務(wù)端其他屬性

  ServerSocket有以下3個(gè)屬性。

  • SO_TIMEOUT:表示等待客戶連接的超時(shí)時(shí)間。一般不設(shè)置,會(huì)持續(xù)等待。
  • SO_REUSEADDR:表示是否允許重用服務(wù)器所綁定的地址。一般不設(shè)置,經(jīng)我的測試沒必要,下面會(huì)進(jìn)行詳解。
  • SO_RCVBUF:表示接收數(shù)據(jù)的緩沖區(qū)的大小。一般不設(shè)置,用系統(tǒng)默認(rèn)就可以了。

  具體詳細(xì)的解釋可以參照下面。

3.3 性能再次提升

  當(dāng)現(xiàn)在的性能還不能滿足需求的時(shí)候,就需要考慮使用NIO,這不是本篇的內(nèi)容,后續(xù)會(huì)貼出。

四、Socket的其它知識(shí)

  其實(shí)如果經(jīng)??从嘘P(guān)網(wǎng)絡(luò)編程的源碼的話,就會(huì)發(fā)現(xiàn)Socket還是有很多設(shè)置的,可以學(xué)著用,但是還是要有一些基本的了解比較好。下面就對(duì)Socket的Java API中涉及到的進(jìn)行簡單講解。首先呢Socket有哪些可以設(shè)置的選項(xiàng),其實(shí)在SocketOptions接口中已經(jīng)都列出來了:

  • int TCP_NODELAY = 0x0001:對(duì)此連接禁用 Nagle 算法。
  • int SO_BINDADDR = 0x000F:此選項(xiàng)為 TCP 或 UDP 套接字在 IP 地址頭中設(shè)置服務(wù)類型或流量類字段。
  • int SO_REUSEADDR = 0x04:設(shè)置套接字的 SO_REUSEADDR。
  • int SO_BROADCAST = 0x0020:此選項(xiàng)啟用和禁用發(fā)送廣播消息的處理能力。
  • int IP_MULTICAST_IF = 0x10:設(shè)置用于發(fā)送多播包的傳出接口。
  • int IP_MULTICAST_IF2 = 0x1f:設(shè)置用于發(fā)送多播包的傳出接口。
  • int IP_MULTICAST_LOOP = 0x12:此選項(xiàng)啟用或禁用多播數(shù)據(jù)報(bào)的本地回送。
  • int IP_TOS = 0x3:此選項(xiàng)為 TCP 或 UDP 套接字在 IP 地址頭中設(shè)置服務(wù)類型或流量類字段。
  • int SO_LINGER = 0x0080:指定關(guān)閉時(shí)逗留的超時(shí)值。
  • int SO_TIMEOUT = 0x1006:設(shè)置阻塞 Socket 操作的超時(shí)值: ServerSocket.accept(); SocketInputStream.read(); DatagramSocket.receive(); 選項(xiàng)必須在進(jìn)入阻塞操作前設(shè)置才能生效。
  • int SO_SNDBUF = 0x1001:設(shè)置傳出網(wǎng)絡(luò) I/O 的平臺(tái)所使用的基礎(chǔ)緩沖區(qū)大小的提示。
  • int SO_RCVBUF = 0x1002:設(shè)置傳入網(wǎng)絡(luò) I/O 的平臺(tái)所使用基礎(chǔ)緩沖區(qū)的大小的提示。
  • int SO_KEEPALIVE = 0x0008:為 TCP 套接字設(shè)置 keepalive 選項(xiàng)時(shí)
  • int SO_OOBINLINE = 0x1003:置 OOBINLINE 選項(xiàng)時(shí),在套接字上接收的所有 TCP 緊急數(shù)據(jù)都將通過套接字輸入流接收。

  上面只是簡單介紹了下(來源Java API),下面有對(duì)其中的某些的詳細(xì)講解,沒講到的后續(xù)如果用到會(huì)補(bǔ)上。

4.1 客戶端綁定端口

  服務(wù)端綁定端口是可以理解的,因?yàn)橐O(jiān)聽指定的端口,但是客戶端為什么要綁定端口,說實(shí)話我覺得這么做的人有點(diǎn)2,或許有的網(wǎng)絡(luò)安全策略配置了端口訪出,使用戶只能使用指定的端口,那么這樣的配置也是挺2的,直接說就可以不要留面子。

  當(dāng)然首先要理解的是,如果沒有指定端口的話,Socket會(huì)自動(dòng)選取一個(gè)可以用的端口,不用瞎操心的。

  但是你非得指定一個(gè)端口也是可以的,做法如下,這時(shí)候就不能用Socket的構(gòu)造方法了,要一步一步來:

// 要連接的服務(wù)端IP地址和端口 String host = "localhost"; int port = 55533; // 與服務(wù)端建立連接 Socket socket = new Socket(); socket.bind(new InetSocketAddress(55534)); socket.connect(new InetSocketAddress(host, port));

  這樣做就可以了,但是當(dāng)這個(gè)程序執(zhí)行完成以后,再次執(zhí)行就會(huì)報(bào),端口占用異常:

java.net.BindException: Address already in use: connect

  明明上一個(gè)Socket已經(jīng)關(guān)閉了,為什么再次使用還會(huì)說已經(jīng)被占用了呢?如果你是用netstat 命令來查看端口的使用情況:

netstat -n|findstr "55533" TCP 127.0.0.1:55534 127.0.0.1:55533 TIME_WAIT

  就會(huì)發(fā)現(xiàn)端口的使用狀態(tài)為TIME_WAIT,說到這你需要有一點(diǎn)TCP連接的基本常識(shí),建議看《》,這是其中的一點(diǎn)摘抄筆記,或許對(duì)理解有一些幫助。

  簡單來說,當(dāng)連接主動(dòng)關(guān)閉后,端口狀態(tài)變?yōu)門IME_WAIT,其他程序依然不能使用這個(gè)端口,防止服務(wù)端因?yàn)槌瑫r(shí)重新發(fā)送的確認(rèn)連接斷開對(duì)新連接的程序造成影響。

  TIME_WAIT的時(shí)間一般有底層決定,一般是2分鐘,還有1分鐘和30秒的。

  所以,客戶端不要綁定端口,不要綁定端口,不要綁定端口。

4.2?讀超時(shí)SO_TIMEOUT

  讀超時(shí)這個(gè)屬性還是比較重要的,當(dāng)Socket優(yōu)化到最后的時(shí)候,往往一個(gè)Socket連接會(huì)一直用下去,那么當(dāng)一端因?yàn)楫惓?dǎo)致連接沒有關(guān)閉,另一方是不應(yīng)該持續(xù)等下去的,所以應(yīng)該設(shè)置一個(gè)讀取的超時(shí)時(shí)間,當(dāng)超過指定的時(shí)間后,還沒有讀到數(shù)據(jù),就假定這個(gè)連接無用,然后拋異常,捕獲異常后關(guān)閉連接就可以了,調(diào)用方法為:

public void setSoTimeout(int timeout) throws SocketException

  timeout - 指定的以毫秒為單位的超時(shí)值。設(shè)置0為持續(xù)等待下去。建議根據(jù)網(wǎng)絡(luò)環(huán)境和實(shí)際生產(chǎn)環(huán)境選擇。

  這個(gè)選項(xiàng)設(shè)置的值將對(duì)以下操作有影響:

  • ServerSocket.accept()
  • SocketInputStream.read()
  • DatagramSocket.receive()

4.3 設(shè)置連接超時(shí)

  這個(gè)連接超時(shí)和上面說的讀超時(shí)不一樣,讀超時(shí)是在建立連接以后,讀數(shù)據(jù)時(shí)使用的,而連接超時(shí)是在進(jìn)行連接的時(shí)候,等待的時(shí)間。

4.4 判斷Socket是否可用

  當(dāng)需要判斷一個(gè)Socket是否可用的時(shí)候,不能簡簡單單判斷是否為null,是否關(guān)閉,下面給出一個(gè)比較全面的判斷Socket是否可用的表達(dá)式,這是根據(jù)Socket自身的一些狀態(tài)進(jìn)行判斷的,它的狀態(tài)有:

  • bound:是否綁定
  • closed:是否關(guān)閉
  • connected:是否連接
  • shutIn:是否關(guān)閉輸入流
  • shutOut:是否關(guān)閉輸出流
socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()&& !socket.isInputShutdown() && !socket.isOutputShutdown()

  建議如此使用,但這只是第一步,保證Socket自身的狀態(tài)是可用的,但是當(dāng)連接正常創(chuàng)建后,上面的屬性如果不調(diào)用本方相應(yīng)的方法是不會(huì)改變的,也就是說如果網(wǎng)絡(luò)斷開、服務(wù)器主動(dòng)斷開,Java底層是不會(huì)檢測到連接斷開并改變Socket的狀態(tài),所以,真實(shí)的檢測連接狀態(tài)還是得通過額外的手段,有兩種方式。

4.4.1 自定義心跳包

  雙方需要約定,什么樣的消息屬于心跳包,什么樣的消息屬于正常消息,假設(shè)你看了上面的章節(jié)現(xiàn)在說就容易理解了,我們定義前兩個(gè)字節(jié)為消息的長度,那么我們就可以定義第3個(gè)字節(jié)為消息的屬性,可以指定一位為消息的類型,1為心跳,0為正常消息。那么要做的有如下:

  • 客戶端發(fā)送心跳包
  • 服務(wù)端獲取消息判斷是否是心跳包,若是丟棄
  • 當(dāng)客戶端發(fā)送心跳包失敗時(shí),就可以斷定連接不可用

  具體的編碼不再貼出,自己實(shí)現(xiàn)即可。

4.4.2 通過發(fā)送緊急數(shù)據(jù)

  Socket自帶一種模式,那就是發(fā)送緊急數(shù)據(jù),這有一個(gè)前提,那就是服務(wù)端的OOBINLINE不能設(shè)置為true,它的默認(rèn)值是false。

  OOBINLINE的true和false影響了什么:

  • 對(duì)客戶端沒有影響
  • 對(duì)服務(wù)端,如果設(shè)置為true,那么服務(wù)端將會(huì)捕獲緊急數(shù)據(jù),這會(huì)對(duì)接收數(shù)據(jù)造成混淆,需要額外判斷

  發(fā)送緊急數(shù)據(jù)通過調(diào)用Socket的方法:

socket.sendUrgentData(0);

  發(fā)送數(shù)據(jù)任意即可,因?yàn)镺OBINLINE為false的時(shí)候,服務(wù)端會(huì)丟棄掉緊急數(shù)據(jù)。

  當(dāng)發(fā)送緊急數(shù)據(jù)報(bào)錯(cuò)以后,我們就會(huì)知道連接不通了。

4.4.3 真的需要判斷連接斷開嗎

  通過上面的兩種方式已經(jīng)可以判斷出連接是否可用,然后我們就可以進(jìn)行后續(xù)操作,可是請(qǐng)大家認(rèn)真考慮下面的問題:

  • 發(fā)送心跳成功時(shí)確認(rèn)連接可用,當(dāng)再次發(fā)送消息時(shí)能保證連接還可用嗎?即便中間的間隔很短
  • 如果連接不可用了,你會(huì)怎么做?重新建立連接再次發(fā)送數(shù)據(jù)?還是說單單只是記錄日志?
  • 如果你打算重新建立連接,那么發(fā)送心跳包的意義何在?為何不在發(fā)送異常時(shí)再新建連接?
  •   如果你認(rèn)真考慮了上面的問題,那么你就會(huì)覺得發(fā)送心跳包完全是沒有必要的操作,通過發(fā)送心跳包來判斷連接是否可用是通過捕獲異常來判斷的。那么我們完全可以在發(fā)送消息報(bào)出IO異常的時(shí)候,在異常中重新發(fā)送一次即可,這兩種方式的編碼有什么不同呢,下面寫一寫偽代碼。

      提前檢測連接是否可用:

    //有一個(gè)連接中的socket Socket socket=... //要發(fā)送的數(shù)據(jù) String data=""; try{//發(fā)送心跳包或者緊急數(shù)據(jù),來檢測連接的可用性 }catch (Excetption e){//打印日志,并重連Socketsocket=new Socket(host,port); } socket.write(data);

      直接發(fā)送數(shù)據(jù),出異常后重新連接再次發(fā)送:

    //有一個(gè)連接中的socket Socket socket=... //要發(fā)送的數(shù)據(jù) String data=""; try{socket.write(data); }catch (Excetption e){//打印日志,并重連Socketsocket=new Socket(host,port);socket.write(data); }

      通過比較可以發(fā)現(xiàn)兩種方式的特點(diǎn),現(xiàn)在簡單介紹下:

    • 兩種方式均可實(shí)現(xiàn)連接斷開重新連接并發(fā)送
    • 提前檢測,再每次發(fā)送消息的時(shí)候都要檢測,影響效率,占用帶寬

      希望大家認(rèn)真考慮,做出自己的選擇。

    4.5 設(shè)置端口重用SO_REUSEADDR?

      首先,創(chuàng)建Socket時(shí),默認(rèn)是禁止的,設(shè)置true有什么作用呢,Java API中是這么介紹的:

    關(guān)閉 TCP 連接時(shí),該連接可能在關(guān)閉后的一段時(shí)間內(nèi)保持超時(shí)狀態(tài)(通常稱為 TIME_WAIT 狀態(tài)或 2MSL 等待狀態(tài))。對(duì)于使用已知套接字地址或端口的應(yīng)用程序而言,如果存在處于超時(shí)狀態(tài)的連接(包括地址和端口),可能不能將套接字綁定到所需的 SocketAddress 上。

    使用 bind(SocketAddress) 綁定套接字前啟用 SO_REUSEADDR 允許在上一個(gè)連接處于超時(shí)狀態(tài)時(shí)綁定套接字。

      一般是用在綁定端口的時(shí)候使用,但是經(jīng)過我的測試建議如下:

    • 服務(wù)端綁定端口后,關(guān)閉服務(wù)端,重新啟動(dòng)后不會(huì)提示端口占用
    • 客戶端綁定端口后,關(guān)閉,即便設(shè)置ReuseAddress為true,即便能綁定端口,連接的時(shí)候還是會(huì)報(bào)端口占用異常

      綜上所述,不建議綁定端口,也沒必要設(shè)置ReuseAddress,當(dāng)然ReuseAddress的底層還是和硬件有關(guān)系的,或許在你的機(jī)器上測試結(jié)果和我不一樣,若是如此和平臺(tái)相關(guān)性差異這么大配置更是不建議使用了。

    4.6 設(shè)置關(guān)閉等待SO_LINGER

      Java API的介紹是:啟用/禁用具有指定逗留時(shí)間(以秒為單位)的 SO_LINGER。最大超時(shí)值是特定于平臺(tái)的。 該設(shè)置僅影響套接字關(guān)閉。?

      大家都是這么說的,當(dāng)調(diào)用Socket的close方法后,沒有發(fā)送的數(shù)據(jù)將不再發(fā)送,設(shè)置這個(gè)值的話,Socket會(huì)等待指定的時(shí)間發(fā)送完數(shù)據(jù)包。說實(shí)話,經(jīng)過我簡單的測試,對(duì)于一般數(shù)據(jù)量來說,幾十K左右,即便直接關(guān)閉Socket的連接,服務(wù)端也是可以收到數(shù)據(jù)的。

      所以對(duì)于一般應(yīng)用沒必要設(shè)置這個(gè)值,當(dāng)數(shù)據(jù)量發(fā)送過大拋出異常時(shí),再來設(shè)置這個(gè)值也不晚。那么到達(dá)逗留超時(shí)值時(shí),套接字將通過 TCP RST 強(qiáng)制性 關(guān)閉。啟用超時(shí)值為零的選項(xiàng)將立即強(qiáng)制關(guān)閉。如果指定的超時(shí)值大于 65,535,則其將被減少到 65,535。?

    4.7 設(shè)置發(fā)送延遲策略TCP_NODELAY

      一般來說當(dāng)客戶端想服務(wù)器發(fā)送數(shù)據(jù)的時(shí)候,會(huì)根據(jù)當(dāng)前數(shù)據(jù)量來決定是否發(fā)送,如果數(shù)據(jù)量過小,那么系統(tǒng)將會(huì)根據(jù)Nagle 算法(暫時(shí)還沒研究),來決定發(fā)送包的合并,也就是說發(fā)送會(huì)有延遲,這在有時(shí)候是致命的,比如說對(duì)實(shí)時(shí)性要求很高的消息發(fā)送,在線對(duì)戰(zhàn)游戲等,即便數(shù)據(jù)量很小也要求立即發(fā)送,如果稍有延遲就會(huì)感覺到卡頓,默認(rèn)情況下Nagle 算法是開啟的,所以如果不打算有延遲,最好關(guān)閉它。這樣一旦有數(shù)據(jù)將會(huì)立即發(fā)送而不會(huì)寫入緩沖區(qū)。

      但是對(duì)延遲要求不是特別高下還是可以使用的,還是可以提升網(wǎng)絡(luò)傳輸效率的。

    4.8 設(shè)置輸出輸出緩沖區(qū)大小SO_RCVBUF/SO_SNDBUF

    • SO_SNDBUF:發(fā)送緩沖
    • SO_RCVBUF:接收緩沖

      默認(rèn)都是8K,如果有需要可以修改,通過相應(yīng)的set方法。不建議修改的太小,設(shè)置太小數(shù)據(jù)傳輸將過于頻繁。太大了將會(huì)造成消息停留。

      不過我對(duì)這個(gè)經(jīng)過測試后有以下結(jié)論:

    • 當(dāng)數(shù)據(jù)填滿緩沖區(qū)時(shí),一定會(huì)發(fā)送
    • 當(dāng)數(shù)據(jù)沒有填滿緩沖區(qū)時(shí)也會(huì)發(fā)送,這個(gè)算法還是上面說的Nagle 算法

    4.9 設(shè)置保持連接存活SO_KEEPALIVE

      雖然說當(dāng)設(shè)置連接連接的讀超時(shí)為0,即無限等待時(shí),Socket不會(huì)被主動(dòng)關(guān)閉,但是總會(huì)有莫名其妙的軟件來檢測你的連接是否有數(shù)據(jù)發(fā)送,長時(shí)間沒有數(shù)據(jù)傳輸?shù)倪B接會(huì)被它們關(guān)閉掉。

      因此通過設(shè)置這個(gè)選項(xiàng)為true,可以有如下效果:當(dāng)2個(gè)小時(shí)(具體的實(shí)現(xiàn)而不同)內(nèi)在任意方向上都沒有跨越套接字交換數(shù)據(jù),則 TCP 會(huì)自動(dòng)發(fā)送一個(gè)保持存活的消息到對(duì)面。將會(huì)有以下三種響應(yīng):

  • 返回期望的ACK。那么不通知應(yīng)用程序(因?yàn)橐磺姓?#xff09;,2 小時(shí)的不活動(dòng)時(shí)間過后,TCP 將發(fā)送另一個(gè)探頭。
  • 對(duì)面返回RST,表明對(duì)面掛了,但是又好了,Socket依然要關(guān)閉
  • 沒有響應(yīng),說明對(duì)面掛了,這時(shí)候關(guān)閉Socket
  •   所以對(duì)于構(gòu)建長時(shí)間連接的Socket還是配置上SO_KEEPALIVE比較好。

    4.10 異常:java.net.SocketException: Connection reset by peer

      這個(gè)異常的含義是,我正在寫數(shù)據(jù)的時(shí)候,你把連接給關(guān)閉了。這個(gè)異常在一般正常的編碼是不會(huì)出現(xiàn)這個(gè)異常的,因?yàn)橛脩敉ǔ?huì)判斷是否讀到流的末尾了,讀到末尾才會(huì)進(jìn)行關(guān)閉操作,如果出現(xiàn)這個(gè)異常,那就檢查一下判斷是否讀到流的末尾邏輯是否正確。

    ?

    五、關(guān)于Socket的理解

    5.1 Socket和TCP/IP

      最近在看《TCP/IP詳解 卷1:協(xié)議》,關(guān)于TCP/IP我覺得講解的非常詳細(xì),我做了點(diǎn)摘抄,可以大致看看,非常建議大家閱讀下這本書。通常TCP/IP分為四層:

      也就是說Socket實(shí)際上是歸屬于應(yīng)用層,使用的事運(yùn)輸層的TCP,使用SocketServer監(jiān)聽的端口,也是可以被Telnet連接的。可以看下面兩行代碼:

    ServerSocket server = new ServerSocket(port); Socket socket = server.accept();

      在什么情況獲取到這個(gè)Socket呢,通過理論加測試,結(jié)論是在三次握手操作后,系統(tǒng)才會(huì)將這個(gè)連接交給應(yīng)用層,ServerSocket 才知道有一個(gè)連接過來了。那么系統(tǒng)當(dāng)接收到一個(gè)TCP連接請(qǐng)求后,如果上層還沒有接受它(假如SocketServer循環(huán)處理Socket,一次一個(gè)),那么系統(tǒng)將緩存這個(gè)連接請(qǐng)求,既然是緩存那么就是有限度的,書上介紹的是緩存3個(gè),但是經(jīng)過我的本機(jī)測試是50個(gè),也就是說,系統(tǒng)將會(huì)為應(yīng)用層的Socket緩存50和TCP連接(這是和系統(tǒng)底層有關(guān)系的),當(dāng)超過指定數(shù)量后,系統(tǒng)將會(huì)拒絕連接。

      假如緩存的TCP連接請(qǐng)求發(fā)送來數(shù)據(jù),那么系統(tǒng)也會(huì)緩存這些數(shù)據(jù),等待SocketServer獲得這個(gè)連接的時(shí)候一并交給它,這個(gè)會(huì)在后期學(xué)習(xí)NIO進(jìn)行詳解。

      換句話說,系統(tǒng)接收TCP連接請(qǐng)求放入緩存隊(duì)列,而SocketServer從緩存隊(duì)列獲取Socket。

      而上面例子中的為了讓服務(wù)端知道發(fā)送完消息的,關(guān)閉輸出流的操作:

    socket.shutdownOutput();

      其實(shí)是對(duì)應(yīng)著四次揮手的第一次:

      也就是上面說的主動(dòng)關(guān)閉,FIN_WAIT_1,這樣服務(wù)端就能得知客戶端發(fā)送完消息,此時(shí)服務(wù)端可以選擇關(guān)閉連接,也可以選擇發(fā)送數(shù)據(jù)后關(guān)閉連接:

      這就是TCP所說的半關(guān)閉。其實(shí)很多知識(shí)都是想通的,多學(xué)點(diǎn)基礎(chǔ)知識(shí)還是有必要的。

    5.2 Socket和RMI

      RMI基礎(chǔ)知識(shí)就不多介紹了(后續(xù)會(huì)寫,敬請(qǐng)期待),現(xiàn)在假定你對(duì)RMI有所了解,那么一般就會(huì)對(duì)這兩種技術(shù)有所比較?;蛘哒f在應(yīng)用的時(shí)候就會(huì)想用那種技術(shù)比較好。

      RMI全稱:Remote Method Invocation-遠(yuǎn)程方法調(diào)用,通過名字其實(shí)就能對(duì)這種技術(shù)有個(gè)初步的了解?,F(xiàn)在我就簡單說說我對(duì)這兩種技術(shù)的想法。

      這個(gè)待寫,等我寫完RMI博客的時(shí)候補(bǔ)上,那時(shí)候會(huì)更細(xì)致的了解下。

    5.3 DatagramSocket與Socket

      這一段涉及到UDP,依然和上面一樣,后續(xù)會(huì)補(bǔ)上。

    5.4?拆包和黏包

      使用Socket通信的時(shí)候,或多或少都聽過拆包和黏包,如果沒聽過而去貿(mào)然編程那么偶爾就會(huì)碰到一些莫名其妙的問題,所有有這方面的知識(shí)還是比較重要的,至少知道怎么發(fā)生,怎么防范。

      現(xiàn)在先簡單說明下拆包和黏包的原因:

    • 拆包:當(dāng)一次發(fā)送(Socket)的數(shù)據(jù)量過大,而底層(TCP/IP)不支持一次發(fā)送那么大的數(shù)據(jù)量,則會(huì)發(fā)生拆包現(xiàn)象。
    • 黏包:當(dāng)在短時(shí)間內(nèi)發(fā)送(Socket)很多數(shù)據(jù)量小的包時(shí),底層(TCP/IP)會(huì)根據(jù)一定的算法(指Nagle)把一些包合作為一個(gè)包發(fā)送。

      首先可以明確的是,大部分情況下我們是不希望發(fā)生拆包和黏包的(如果希望發(fā)生,什么都去做即可),那么怎么去避免呢,下面進(jìn)行詳解?

    5.4.1 黏包

      首先我們應(yīng)該正確看待黏包,黏包實(shí)際上是對(duì)網(wǎng)絡(luò)通信的一種優(yōu)化,假如說上層只發(fā)送一個(gè)字節(jié)數(shù)據(jù),而底層卻發(fā)送了41個(gè)字節(jié),其中20字節(jié)的I P首部、 20字節(jié)的T C P首部和1個(gè)字節(jié)的數(shù)據(jù),而且發(fā)送完后還需要確認(rèn),這么做浪費(fèi)了帶寬,量大時(shí)還會(huì)造成網(wǎng)絡(luò)擁堵。當(dāng)然它還是有一定的缺點(diǎn)的,就是因?yàn)樗鼤?huì)合并一些包會(huì)導(dǎo)致數(shù)據(jù)不能立即發(fā)送出去,會(huì)造成延遲,如果能接受(一般延遲為200ms),那么還是不建議關(guān)閉這種優(yōu)化,如果因?yàn)轲ぐ鼤?huì)造成業(yè)務(wù)上的錯(cuò)誤,那么請(qǐng)改正你的服務(wù)端讀取算法(協(xié)議),因?yàn)榧幢悴话l(fā)生黏包,在服務(wù)端緩存區(qū)也可能會(huì)合并起來一起提交給上層,推薦使用長度+類型+數(shù)據(jù)模式。

      如果不希望發(fā)生黏包,那么通過禁用TCP_NODELAY即可,Socket中也有相應(yīng)的方法:

    void setTcpNoDelay(boolean on)

      通過設(shè)置為true即可防止在發(fā)送的時(shí)候黏包,但是當(dāng)發(fā)送的速率大于讀取的速率時(shí),在服務(wù)端也會(huì)發(fā)生黏包,即因服務(wù)端讀取過慢,導(dǎo)致它一次可能讀取多個(gè)包。

    5.4.2 拆包

      這個(gè)問題應(yīng)該引起重視,在TCP/IP詳解中說過:最大報(bào)文段長度(MSS)表示TCP傳往另一端的最大塊數(shù)據(jù)的長度。當(dāng)一個(gè)連接建立時(shí),連接的雙方都要通告各自的 MSS。客戶端會(huì)盡量滿足服務(wù)端的要求且不能大于服務(wù)端的MSS值,當(dāng)沒有協(xié)商時(shí),會(huì)使用值536字節(jié)。雖然看起來MSS值越大越好,但是考慮到一些其他情況,這個(gè)值還是不太好確定,具體詳見《TCP/IP詳解 卷1:協(xié)議》。

      如何應(yīng)對(duì)拆包,其實(shí)在上面2.3節(jié)已經(jīng)介紹過了,那就是如何表明發(fā)送完一條消息了,對(duì)于已知數(shù)據(jù)長度的模式,可以構(gòu)造相同大小的數(shù)組,循環(huán)讀取,示例代碼如下:

    int length=1024;//這個(gè)是讀取的到數(shù)據(jù)長度,現(xiàn)假定1024 byte[] data=new byte[1024]; int readLength=0; while(readLength<length){int read = inputStream.read(data, readLength, length-readLength);readLength+=read; }

      這樣當(dāng)循環(huán)結(jié)束后,就能讀取到完整的一條數(shù)據(jù),而不需要考慮拆包了。

    ?

      單單關(guān)于Java的Socket編程已經(jīng)基本介紹完成了,當(dāng)然還有更深層次的知識(shí)沒有涉及到,后續(xù)如果能有接觸也會(huì)寫出來,希望我的文章能幫助到有需要的人,如果有什么不對(duì)的地方請(qǐng)指出,禁止轉(zhuǎn)載。

    轉(zhuǎn)載于:https://www.cnblogs.com/tc310/p/10611243.html

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的【转】Java Socket编程基础及深入讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

    国产粉嫩在线观看 | 国产精品不卡 | wwwwww国产 | 黄a在线观看 | 色综合久久久久久久久五月 | 国产小视频在线观看免费 | 亚洲精品资源在线 | 国产精品第二十页 | wwwww.国产 | 亚洲精品国产精品乱码不99热 | 人人澡人人添人人爽一区二区 | 国产亚洲精品福利 | 免费一级片在线观看 | 日韩网站在线免费观看 | 91中文在线| 一级黄色a视频 | 国产成人精品一区二区三区福利 | 欧洲性视频 | 欧美日本中文字幕 | 欧美激情xxxx性bbbb | 四虎国产精品免费观看视频优播 | 五月综合色 | 亚洲成人黄色在线观看 | 激情五月综合网 | 久久高清精品 | www五月天 | 日本中文一区二区 | 免费一级片在线观看 | 天天综合久久综合 | 91精品国产综合久久福利不卡 | 天天色 天天 | 黄网站色 | 手机av电影在线观看 | av丝袜美腿 | 免费一级片久久 | 97国产在线播放 | 久久精品一区二区国产 | 韩国av一区二区三区在线观看 | 久久综合色8888 | 激情网站网址 | 中文字幕一二 | 国产视频1区2区3区 久久夜视频 | 日韩欧美综合 | av免费看电影 | 日韩一区正在播放 | 欧美a视频在线观看 | 欧美久久99 | 一本一本久久a久久精品综合小说 | 九九热精品视频在线播放 | 久久久不卡影院 | 欧美专区国产专区 | 超碰人人草| 成人在线播放网站 | 五月婷婷影院 | 97超碰精品| 中文字幕在线日本 | 婷婷精品在线视频 | 日韩中文字幕a | 在线视频成人 | 毛片精品免费在线观看 | 在线观看av的网站 | 国产精品麻豆视频 | 国产欧美在线一区 | 国产视频日韩视频欧美视频 | 久久午夜免费视频 | 日韩动态视频 | 色片网站在线观看 | av在线激情 | 一区二区三区四区精品 | 免费视频 三区 | 97在线观视频免费观看 | 男女激情麻豆 | 久久久久久久久久久影院 | 黄色片视频在线观看 | 五月婷婷激情六月 | 人人人爽 | 精品国产一区二区三区久久久久久 | 亚洲精品综合在线观看 | 日本精品久久久久中文字幕5 | 成人在线视频网 | 婷婷色中文| 国产精品丝袜久久久久久久不卡 | 狠狠色狠狠色综合日日92 | 国产做爰视频 | 国内精品99 | 91免费黄视频 | 国产美女精品视频 | 欧美有色 | 欧美一级片在线 | 国产精品久久一区二区三区不卡 | 麻豆国产露脸在线观看 | 99精品免费观看 | 国产香蕉97碰碰碰视频在线观看 | 在线国产99 | 99热这里只有精品在线观看 | 免费看一级特黄a大片 | 中文字幕一区二区三区视频 | 免费观看91 | 久久99视频免费观看 | 涩涩色亚洲一区 | 在线免费av电影 | 日韩精品一区不卡 | 成人av一区二区兰花在线播放 | 国产一级不卡毛片 | 成人黄色在线观看视频 | 日韩在线播放视频 | 日韩 在线a | 成人国产精品一区二区 | 国产字幕在线播放 | 丁香在线观看完整电影视频 | 天天射天天艹 | 中文av日韩| www.天天射 | 韩国视频一区二区三区 | 国产黄色美女 | 国产精品不卡一区 | 久久综合亚洲鲁鲁五月久久 | 精品国自产在线观看 | 综合网婷婷| 麻豆视频在线观看免费 | 国产高清在线a视频大全 | 在线观看色网 | 99视频精品视频高清免费 | 国产视频日本 | 在线观看视频中文字幕 | 黄色app网站在线观看 | 成人黄色在线看 | 狠狠狠色丁香婷婷综合激情 | 午夜国产在线观看 | 天天艹天天干天天 | 日本高清久久久 | 三级在线视频播放 | 亚洲激情视频 | 亚洲精品午夜视频 | 欧美日韩国产二区三区 | 色婷婷啪啪免费在线电影观看 | 国产探花 | 日韩美女久久 | 天天操天天添 | 18国产精品福利片久久婷 | 成人午夜免费福利 | 日本激情视频中文字幕 | 五月婷婷视频在线 | 国产精品毛片一区二区 | 日韩精品在线播放 | 国产黄色视 | 亚洲蜜桃在线 | av黄免费看 | 特黄特色特刺激视频免费播放 | 日韩av成人在线观看 | 欧美午夜精品久久久久久浪潮 | 成人综合日日夜夜 | 亚洲激情在线视频 | 香蕉影视在线观看 | 视频在线观看91 | 日韩免费一区二区三区 | av三级在线免费观看 | 96精品在线 | 国产精品 日韩 欧美 | 国产一级在线观看视频 | 综合久色 | 久久99视频精品 | 久久香蕉一区 | 在线免费看黄色 | 色中色综合 | 一级全黄毛片 | 日韩在线观看视频免费 | 亚洲人成在线观看 | 999精品 | 在线v片免费观看视频 | 国产视频一区精品 | 在线免费av网站 | 综合久久婷婷 | 亚洲精品小视频 | 国产一级电影 | 国内精品久久久久国产 | 99久久日韩精品免费热麻豆美女 | 91亚色视频在线观看 | 五月婷婷综合在线观看 | 日韩大片在线看 | 国产一区在线视频播放 | 在线观看的av网站 | 精品视频免费 | 国产99在线播放 | www.久草视频 | 亚洲欧美成人网 | 久久视频在线观看中文字幕 | 亚洲最新av在线 | 成人午夜电影在线播放 | 黄色网大全 | 91精品国产自产在线观看永久 | 狠狠干成人 | 中国一级特黄毛片大片久久 | 五月婷婷色综合 | 中文字幕123区| 视频1区2区 | 国产在线一区二区三区播放 | 国产一级片网站 | 色婷婷综合久久久久 | 男女男视频 | 美女在线观看av | 精品国产一区二区三区久久久 | 国产精品久久久久久久久久久不卡 | 91精品伦理 | 91成人免费看 | 中文字幕在线观看播放 | 成人av在线网 | 久草在线免费在线观看 | 午夜精品久久久 | 天天操天天射天天操 | 亚洲精品www | 精品久久久久久久久久久久久久久久 | 精品免费观看视频 | 久久久久www | 日韩欧美在线播放 | 日韩欧美视频一区二区三区 | 人人爱人人添 | 一级淫片在线观看 | 国产一级黄色电影 | 91精品啪在线观看国产线免费 | 中文字幕在线播放一区二区 | 精品国产精品久久 | 日本精品久久久久中文字幕 | 成年人电影免费看 | 丁香视频 | 久久久久久久久久久久亚洲 | 成人av资源 | 正在播放亚洲精品 | 国产xxxxx在线观看 | 国产色a在线观看 | 精品一区二区三区久久久 | 国产精品一区二区无线 | 亚洲片在线观看 | 亚洲激情小视频 | 亚洲精品色 | 久久国产免费 | 欧美激情综合五月色丁香小说 | 特黄特色特刺激视频免费播放 | 九九在线视频 | 97理论电影 | 色在线最新 | www成人精品| 婷婷久久综合九色综合 | www.午夜色.com | 国产中文字幕第一页 | 欧美网站黄色 | 欧美精品乱码99久久影院 | 九九综合九九 | 色欧美日韩 | 国产丝袜一区二区三区 | 久草国产在线观看 | 日韩在线视频网址 | 国产一区麻豆 | 99精品亚洲 | 激情综合六月 | jizz999| 日日操天天爽 | 亚洲精品美女免费 | 天天插伊人 | 国产一级大片在线观看 | 一区二区三区精品在线 | 久久精品一区二区国产 | 97色婷婷| 国产精品第2页 | 日韩美一区二区三区 | 国产美女主播精品一区二区三区 | 婷婷社区五月天 | 国产一级高清视频 | 麻豆视频国产在线观看 | 三级av网| 日本在线成人 | 有码中文字幕在线观看 | 午夜精品中文字幕 | 亚洲精品白浆高清久久久久久 | 久久精品中文字幕免费mv | 操操碰| 亚洲一级片在线观看 | 在线直播av | 国产精品久久久久久久久久新婚 | 亚洲成av人影片在线观看 | 激情网站免费观看 | 国产高清免费 | 亚洲成av | 97av色| 久久兔费看a级 | 久久成人免费电影 | 天天射天天色天天干 | 91网址在线看 | 国产精品麻豆91 | 久久久久久久久毛片精品 | 91精品专区 | 亚洲视频一区二区三区在线观看 | 成 人 黄 色 视频免费播放 | 久久久精品小视频 | 久久人人爽 | 色诱亚洲精品久久久久久 | 特级西西444www大精品视频免费看 | 日韩av一区在线观看 | 国产精品精品 | 精品国产一区二区三区日日嗨 | 在线免费av观看 | 久久激情小说 | 伊甸园永久入口www 99热 精品在线 | 粉嫩一区二区三区粉嫩91 | 国产麻豆视频网站 | 精品一区二区免费视频 | 午夜久久久久久久久久久 | 东方av免费在线观看 | 久久情侣偷拍 | 在线观看视频国产一区 | 欧美性极品xxxx做受 | 操操操夜夜操 | 玖玖精品在线 | 免费看一级黄色大全 | av先锋影音少妇 | 日韩区在线观看 | 在线观看一区 | 91理论电影 | 91精品蜜桃 | 色噜噜日韩精品欧美一区二区 | 国产91对白在线播 | 午夜一级免费电影 | 国产色黄网站 | 97av影院| 国产成年免费视频 | 韩国一区二区在线观看 | av高清不卡 | 999免费视频 | 久久免费视频8 | 婷婷中文字幕在线观看 | 免费99精品国产自在在线 | 国产人成看黄久久久久久久久 | 麻豆av电影| 色噜噜狠狠狠狠色综合 | 国产成人av片 | 国产在线一区二区三区播放 | 干亚洲少妇| 免费成人结看片 | 91黄色影视 | 久久久人人爽 | 91看片网址| 国产黄色av | 91麻豆精品久久久久久 | 国精产品永久999 | 8x成人在线 | 成人在线观看av | 久草在线视频资源 | 在线观看国产日韩 | 视频在线99 | 久久狠狠婷婷 | 丁香在线观看完整电影视频 | 日韩一区二区三免费高清在线观看 | 91av电影在线 | 久久精品一二三区 | 亚洲在线视频网站 | 日本在线观看一区二区 | 黄色a一级片 | 中文国产字幕 | 天天操天天舔天天爽 | 五月精品 | 欧美激情精品一区 | 天海冀一区二区三区 | 成人免费观看网址 | 在线看国产视频 | 五月的婷婷 | 西西444www高清大胆 | 精品在线99 | 亚洲日本一区二区在线 | 伊人影院在线观看 | 国产无套精品久久久久久 | 一区二区三区四区五区六区 | 国产亚洲精品bv在线观看 | a视频在线看 | 亚洲国产视频网站 | 97在线公开视频 | 国产91区 | 久99久久| 人人狠狠综合久久亚洲婷 | 亚洲天堂自拍视频 | 久久精品aaa | 91视频免费网址 | 国际精品久久久 | 亚洲综合在线一区二区三区 | 玖草影院 | 天堂av色婷婷一区二区三区 | 美女国产在线 | 三级免费黄 | 久久有精品 | av电影在线播放 | 97精品超碰一区二区三区 | 国产一级片视频 | 亚洲日韩欧美一区二区在线 | 福利视频在线看 | 99综合影院在线 | 狠狠狠色丁香综合久久天下网 | 五月天激情综合 | 精品在线你懂的 | 日韩欧美久久 | 亚洲黄色a | 久久免费的精品国产v∧ | 国产破处在线播放 | 99热精品在线观看 | 三级av在线 | 麻豆精品91 | 国产又粗又猛又黄视频 | 69精品在线 | 国产福利精品视频 | 91视频久久久| 搡bbbb搡bbb视频 | 狠狠色噜噜狠狠狠合久 | 伊人网综合在线观看 | 久久综合五月婷婷 | 日本一区二区免费在线观看 | 亚洲一区二区精品 | 久久国产精品久久国产精品 | 日韩美视频 | 黄色在线网站噜噜噜 | 国内精品视频在线 | 香蕉视频在线免费 | 97超碰伊人 | 狠狠色丁香久久婷婷综 | 亚洲精品乱码久久久久久高潮 | 国产免费视频在线 | 99久久精品国产免费看不卡 | 久久成人毛片 | 深爱五月网| 午夜精品久久久久久久99 | 91精品人成在线观看 | 日韩av在线小说 | 97人人人| 亚洲人成在线观看 | 精品国产一区二区久久 | 久久一区国产 | 国产亚州精品视频 | 日韩天堂在线观看 | 天海冀一区二区三区 | 中文字幕国产 | 免费在线播放黄色 | 一本一道波多野毛片中文在线 | 国产真实在线 | 国产视频不卡 | 亚洲做受高潮欧美裸体 | 99精品亚洲 | 国产日韩精品在线观看 | 成年人视频在线 | 久久久久免费精品视频 | 天天色天天 | 国产在线中文字幕 | 国产精品麻豆果冻传媒在线播放 | 草草草影院 | 5月丁香婷婷综合 | 久久久久久久久影院 | 国产福利91精品张津瑜 | 亚洲成人资源在线观看 | 天天插日日射 | 久久久精品成人 | 狠狠色丁香九九婷婷综合五月 | 欧美一级小视频 | 深夜免费福利网站 | 99看视频在线观看 | 亚洲 综合 精品 | av视屏在线 | 国产成人免费在线 | 中文字幕一区二区三区在线播放 | 成人免费观看大片 | 欧美国产日韩一区二区三区 | 狠狠狠狠狠狠狠狠 | 91一区一区三区 | 日韩免费视频一区二区 | 99视频偷窥在线精品国自产拍 | 久久久久久免费视频 | www亚洲精品 | 中文字幕专区高清在线观看 | 99久久一区| 99久久精品国产一区二区成人 | 黄网站色视频免费观看 | 中文字幕亚洲不卡 | 中文字幕在线人 | 国产在线 一区二区三区 | 六月丁香婷婷久久 | 天天色天天射天天综合网 | 黄色成人av网址 | 免费a级观看 | 国产精品不卡一区 | av观看在线观看 | 成人91视频 | 视频国产在线观看18 | 久久人人爽人人爽 | 人人射av| 成年人黄色在线观看 | 免费色网 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 久久久亚洲麻豆日韩精品一区三区 | 久久人人精品 | 亚洲天堂自拍视频 | 在线观看视频一区二区三区 | 亚洲专区 国产精品 | 狠狠干激情 | 欧美久久成人 | 成人av.com| 日本在线成人 | 97精产国品一二三产区在线 | 亚洲欧美在线视频免费 | 毛片基地黄久久久久久天堂 | 99久久精品免费看国产四区 | 国产福利91精品一区二区三区 | 亚洲爽爽网| 婷婷香蕉 | 久久国产精品视频观看 | 国产中文字幕av | va视频在线 | 久久99精品国产 | 成人在线播放网站 | 在线视频你懂得 | 国产精品女主播一区二区三区 | 99视频在线精品免费观看2 | 亚洲在线网址 | 最近免费中文视频 | 精品久久久久久亚洲综合网 | 在线视频福利 | 国产精品一区二区无线 | 国产精品视频在线观看 | 综合久久网| 色播五月激情五月 | 天天爽天天搞 | 国产黄色特级片 | 国产精品欧美久久久久天天影视 | 日韩精品中文字幕av | 中文字幕高清av | 国产最新在线观看 | 国产精品一区二区三区观看 | 伊人天天狠天天添日日拍 | 久久深夜 | 日韩视频www | 99精品偷拍视频一区二区三区 | 国产美女在线免费观看 | 亚洲电影网站 | 久久激情综合网 | 国内精品中文字幕 | 中文字幕在线视频精品 | 亚洲高清精品在线 | 国产玖玖精品视频 | 在线观看av中文字幕 | 久久免费视频精品 | 视频国产在线 | 天天色天天色天天色 | 亚洲精品a区 | 91九色在线观看 | 亚洲欧洲视频 | 欧美成人基地 | 黄色91在线观看 | 91精品在线播放 | 免费色视频在线 | 日韩欧美观看 | 国产九九热视频 | 久久综合免费 | 久久1电影院 | 久久精品一区二区三区中文字幕 | 亚洲一区日韩精品 | 亚洲国产日韩欧美在线 | 成人免费在线视频 | 欧美专区国产专区 | 亚洲va欧美va人人爽春色影视 | 超碰在线日韩 | 免费国产在线视频 | 91精品久久久久久综合乱菊 | 亚洲精品综合在线观看 | 在线免费观看一区二区三区 | 九九久久免费 | 国产成人久久av977小说 | 亚洲国产中文字幕在线观看 | 中文字幕一区二区三区四区在线视频 | 国产专区在线 | 久久精品一区二区三区四区 | 天天干夜夜想 | 片网站| 美女视频黄是免费的 | 成人免费在线播放 | 日本中文字幕影院 | 高清一区二区 | 欧洲精品码一区二区三区免费看 | 麻豆视频免费入口 | 免费看一级黄色大全 | 欧美午夜激情网 | 97视频在线观看成人 | 亚洲自拍自偷 | 欧美性护士 | 国产91勾搭技师精品 | 在线观看91久久久久久 | 日本激情视频中文字幕 | 丝袜少妇在线 | 最新高清无码专区 | 99久久超碰中文字幕伊人 | 免费观看av | 欧美视频99| 国产免费一区二区三区最新6 | 精品uu| 欧美少妇bbwhd | 人人舔人人 | 亚洲视频99 | 国产一区二区在线免费视频 | 综合网天天射 | 久久精品99国产精品日本 | 五月婷婷综合色拍 | 国产视频精选 | 久久久午夜视频 | av在线看网站 | 日韩精品专区在线影院重磅 | 中文字幕999 | 久久8精品 | 欧美日韩中文在线观看 | 久久精品网站免费观看 | 精品免费国产一区二区三区四区 | 91久色蝌蚪 | 欧美成年人在线视频 | 精品国产乱码久久久久久1区二区 | 久久兔费看a级 | 日日操天天操狠狠操 | 亚洲综合最新在线 | 国产亚洲精品av | 国产中文字幕av | 精品久久久久国产免费第一页 | 国产成人精品一区一区一区 | 国产一区二区精品久久 | 久久久久久久综合色一本 | 久久久色 | 中文字幕日本在线观看 | 亚洲综合涩 | 成年人免费看av | 亚洲h视频在线 | 亚洲欧洲国产精品 | 日韩av午夜 | 久热只有精品 | 日本中文字幕久久 | 超黄视频网站 | 日本精品视频在线观看 | 国产精品嫩草影院9 | 在线视频麻豆 | 黄色美女免费网站 | 伊人热| 超碰人人av| 天天综合久久 | 日韩中文在线电影 | 亚洲国产剧情av | 深爱开心激情网 | 久久久久福利视频 | 国产精品久久影院 | 久热只有精品 | 久久久精品欧美一区二区免费 | 国产在线v | 欧美精品国产综合久久 | 免费a视频在线 | 午夜精品久久久久久久爽 | 日本激情视频中文字幕 | 成人影片在线免费观看 | 人人爽人人搞 | 久草网在线 | 综合色综合色 | 91精品国产91久久久久久三级 | 亚洲国产精品成人va在线观看 | 97在线观看免费 | 中文字幕中文字幕在线中文字幕三区 | 久精品视频在线观看 | 婷婷丁香五 | 免费在线观看黄色网 | 91精品成人 | 99久久日韩精品视频免费在线观看 | 在线视频你懂 | 日韩三级中文字幕 | 在线免费观看麻豆视频 | 久久精国产 | 欧美色888| 日韩在线中文字幕 | 亚洲片在线| 国产精品久久久999 国产91九色视频 | 狂野欧美激情性xxxx欧美 | 欧美激情操 | 久久99精品波多结衣一区 | 狠狠躁夜夜躁人人爽视频 | 亚洲视频一 | av高清在线观看 | 最近中文字幕免费大全 | 欧美一二三区在线观看 | 黄色福利| 久久99久久精品 | 成片人卡1卡2卡3手机免费看 | 成人免费在线网 | 成人av资源在线 | 国产亚洲精品电影 | 国产精品久久久久久久久久了 | 久久午夜精品影院一区 | 欧美日韩在线精品一区二区 | 欧美日韩性视频 | 久久人人射| 亚洲精品av中文字幕在线在线 | 狠狠地日 | 操操操天天操 | 色噜噜在线观看 | av免费在线网站 | 日韩在线观看中文字幕 | 日本精品久久久久中文字幕 | 国产综合香蕉五月婷在线 | 在线免费观看涩涩 | 西西4444www大胆无视频 | 久草手机视频 | 超碰在线色 | 国产精品成人自产拍在线观看 | 99视频在线精品国自产拍免费观看 | 国产亚洲视频系列 | www.xxx.性狂虐 | 国产精品成人一区 | 日韩av一卡二卡三卡 | 婷婷激情五月 | 99精品一级欧美片免费播放 | www.国产在线 | 人人看人人草 | 午夜精品一区二区三区在线播放 | 久久国产精品免费视频 | 鲁一鲁影院 | 91亚洲欧美 | 91视频免费观看 | 天天夜夜狠狠操 | 91精品国产成人观看 | 日韩精品第1页 | 成人免费视频观看 | 99中文字幕视频 | 黄色福利视频网站 | av天天草| 国产又粗又长的视频 | 国产91对白在线 | 四虎永久免费网站 | 中文字幕字幕中文 | 国产成人久久精品亚洲 | 久久精品毛片 | 精品国产理论 | 亚洲天堂精品 | 蜜桃传媒一区二区 | 精品在线观看一区二区 | 99久久er热在这里只有精品66 | 不卡的av中文字幕 | 国产日韩精品一区二区三区在线 | 久久这里只有精品视频首页 | 亚洲精品国产视频 | 久视频在线 | 一区二区三区在线不卡 | 国产欧美综合在线观看 | 日韩理论在线观看 | 国产一区视频导航 | 国产视频精品久久 | 久久久久这里只有精品 | 亚洲精品久久视频 | 中文字幕 国产精品 | 涩涩色亚洲一区 | 国产精品美女久久久网av | 日韩激情第一页 | 黄色av一区二区三区 | 欧美视频网址 | 97精品国自产拍在线观看 | 国产乱码精品一区二区蜜臀 | 欧美日韩高清一区二区三区 | 2021国产视频 | 日韩精品视频免费专区在线播放 | 成人蜜桃视频 | 狠狠色丁香婷婷综合久小说久 | 五月天丁香 | 在线免费观看不卡av | 五月婷婷婷婷婷 | 久草在线资源观看 | av免费在线观看1 | 成人免费在线播放 | 色黄视频免费观看 | 亚洲一级特黄 | 欧洲精品亚洲精品 | 天天操天天草 | 精品国产成人在线 | 四虎国产永久在线精品 | 午夜色站 | 成人国产精品久久久春色 | 国产一级视频在线免费观看 | 在线观看亚洲视频 | 国产日本在线观看 | 天天干天天干天天色 | 四虎成人精品永久免费av | 成人午夜影院 | 一区二区中文字幕在线观看 | 六月婷操 | 五月天综合 | 人人看人人草 | 超碰人人干人人 | 视频在线观看入口黄最新永久免费国产 | av国产网站 | 国产一级二级三级视频 | 婷婷国产v亚洲v欧美久久 | 国产综合片| 看v片 | 最近免费观看的电影完整版 | 亚洲欧美日韩国产一区二区三区 | 国产精品一区二区三区在线看 | 91精品少妇偷拍99 | 西西www444 | 超碰大片 | 国产又粗又猛又色 | 国产精品夜夜夜一区二区三区尤 | 最新黄色av网址 | www99精品| 国模精品在线 | 久久国产精品99久久久久久老狼 | 色综合亚洲精品激情狠狠 | 久久福利综合 | 亚洲影院色 | 久草精品电影 | 99久久精品无免国产免费 | 久久久精品二区 | 久久99精品久久久久久秒播蜜臀 | 亚洲香蕉在线观看 | 久久久免费精品视频 | 免费网站污 | 奇米影视777影音先锋 | 人人爽夜夜爽 | 亚洲天天 | 69久久99精品久久久久婷婷 | 福利网址在线观看 | 国产香蕉在线 | 国产视频在线播放 | 麻豆va一区二区三区久久浪 | 日韩欧美成 | 最近中文字幕完整视频高清1 | 美女网站色在线观看 | 四虎影视成人 | 免费黄在线观看 | 五月天综合色 | 久久精品国产成人精品 | 国产最新视频在线 | 免费看黄色毛片 | 久久精品中文字幕一区二区三区 | 亚洲波多野结衣 | 最近中文字幕高清字幕免费mv | av在线免费在线观看 | 超碰在线资源 | 国产精品丝袜久久久久久久不卡 | 成人网大片| 国内丰满少妇猛烈精品播放 | 香蕉视频4aa | 激情欧美一区二区免费视频 | 免费在线看成人av | 9797在线看片亚洲精品 | 中文字幕第一页在线播放 | 麻豆播放 | 欧美激情在线看 | 久久理论电影网 | 婷婷性综合| 麻豆91视频 | 国产福利91精品张津瑜 | 91成人短视频在线观看 | 91成人小视频 | 欧美激情视频一区 | 国产精品一区二区av麻豆 | 日韩美av在线| 日韩精品免费一区 | 欧美日韩伦理在线 | 狠狠操操操 | 91精品资源 | 欧美 日韩精品 | 91精品一区国产高清在线gif | 国产福利在线免费观看 | 九九久久国产 | 欧美日韩有码 | 丁香午夜 | 亚洲aaa级| 91香蕉视频黄色 | 国产精品美女久久久久久久 | 99精品福利 | 91av视频在线播放 | 国产精品毛片一区视频播不卡 | 欧美一区二视频在线免费观看 | 精品国产aⅴ一区二区三区 在线直播av | 免费在线成人av | 国产成人精品亚洲精品 | 国产成人av免费在线观看 | 91尤物国产尤物福利在线播放 | 国产精品一区二区久久精品爱微奶 | 7777精品伊人久久久大香线蕉 | 亚洲成人免费观看 | 在线播放一区二区三区 | 天天曰夜夜爽 | 一级片黄色片网站 | 国产精品地址 | 国产午夜精品福利视频 | 亚洲在线观看av | 国产精品免费一区二区 | 色播99 | 日韩黄色大片在线观看 | 在线精品视频在线观看高清 | 欧美一区二区三区不卡 | 亚洲成人国产精品 | 日本精品一区二区 | 免费看一级特黄a大片 | 在线看一级片 | 中文字幕免费高 | 免费观看国产视频 | 久久 精品一区 | 免费97视频 | 久久人人爽爽 | 久久久久成人精品 | 成人久久久久久久久久 | 精油按摩av | 搡bbbb搡bbb视频| 激情五月六月婷婷 | 99久久er热在这里只有精品15 | 精品国产免费一区二区三区五区 | 中文字幕无吗 | 亚州人成在线播放 | 九九免费在线观看视频 | 免费观看国产精品 | 99久久电影 | 亚洲精品在线播放视频 | 国产视频在线观看一区 | 欧美一级电影在线观看 | 六月婷婷久香在线视频 | 欧美成人中文字幕 | 99草视频在线观看 | 美女很黄免费网站 | 亚洲精品视频在线播放 | 免费成人av网站 | 久久国产精品久久w女人spa | 欧美日韩国产精品一区二区三区 | 欧美日韩国产一区二区三区在线观看 | 精品999久久久 | 国产一区二区三区高清播放 | 国产剧在线观看片 | 97在线精品 | 日韩免费在线 | 99精品在线看 | 激情影音先锋 | 人人澡人人爽欧一区 | 国产色拍| 国产精品一区免费观看 | 欧美日韩国产在线一区 | 中文字幕在线观看一区 | 精油按摩av | 国产欧美久久久精品影院 | 亚洲精品乱码久久久久久蜜桃不爽 | 在线岛国av | 98福利在线| 国产亚洲精品精品精品 | 国产理论免费 | 日韩一区二区三区在线看 | 99国产一区二区三精品乱码 | 激情综合色综合久久综合 | 久草精品视频 | 欧美天天射 | 黄色软件视频大全免费下载 | 国产一级在线视频 | 一区二区精品在线 | 韩国精品在线观看 | 中文字幕在线免费看线人 | 成人午夜在线电影 | 五月天网站在线 | 夜夜躁狠狠燥 | 亚洲 欧美变态 另类 综合 | 中文字幕亚洲情99在线 | wwwwwww色 | 欧美精品久久久久久久久久丰满 | 亚洲精品男人的天堂 | 日韩精品一区二区三区中文字幕 | 日韩网站在线看片你懂的 | 涩涩网站在线看 | 美女视频久久黄 | 亚洲综合精品在线 | 免费av大片 | 久久精品人 | 视频国产在线观看18 | 国产精久久久久久久 | 操少妇视频 | 国产成人在线观看免费 | 亚洲一区二区精品在线 | 91精选| 九九九九九国产 | 免费中文字幕在线观看 | 久久免费福利视频 | 三级性生活视频 | 国产美女在线免费观看 | 久久国产视频网 | 成人网色| 国产一级片免费视频 | 久久黄网站 | 国产精品久久久久久久久久尿 | 在线免费日韩 | 精品久久久久久亚洲综合网站 | 国产婷婷视频在线 | 2022久久国产露脸精品国产 | www免费视频com━ | 玖玖玖在线 | 碰天天操天天 | 亚洲精品国产综合99久久夜夜嗨 | 久精品视频在线观看 | 国产成人精品不卡 | 亚洲精品日韩在线观看 |