日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Netty】NIO 网络编程 聊天室案例

發布時間:2025/6/17 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Netty】NIO 网络编程 聊天室案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、 NIO 聊天室需求
  • 二、 NIO 聊天室 服務器端 代碼分析
  • 三、 NIO 聊天室 客戶端 代碼分析
  • 四、 NIO 聊天室 服務器端 完整代碼
  • 五、 NIO 聊天室 客戶端 完整代碼
  • 六、 NIO 聊天室 運行





一、 NIO 聊天室需求



1 . NIO 聊天室需求 :


① 服務器 客戶端 通信 : 服務器 與 客戶端 實現 雙向通信 ; 服務器可以寫出數據到客戶端 , 也能讀取客戶端的數據 ; 客戶端可以寫出數據到服務器端 , 也可以讀取服務器端的數據 ;

② 多人聊天 : 一個服務器 與 多個客戶端 進行數據交互 , 同時還要實現將某一個客戶端的數據轉發給其它客戶端 ;

③ 用戶狀態監測 : 服務器可以檢測用戶的 上線 , 離線 狀態 ;



2 . 數據傳輸細節 :


① 上線監聽 : 當有客戶端連接時 , 服務器檢測到用戶上線 , 服務器將該用戶上線狀態通知給其它客戶端 ;

② 下線監聽 : 如果有客戶端離線 , 服務器檢測到連接斷開 , 服務器將該用戶離線的狀態通知給聊天室的其它客戶端 ;

③ 聊天信息轉發 : 客戶端發送消息時 , 服務器端接收到該數據 , 并轉發給聊天室的其它用戶客戶端 ;





二、 NIO 聊天室 服務器端 代碼分析



服務器端的連接管理流程 : 創建 服務器套接字通道 ( ServerSocketChannel ) , 將該通道注冊給 選擇器 ( Selector ) , 選擇器開啟監聽 , 監聽到客戶端連接 , 就創建一個 套接字通道 ( SocketChannel ) , 注冊給選擇器 ;


服務器端的消息轉發流程 : 服務器端收到客戶端發送的消息 , 將該消息轉發給除該客戶端外的其它客戶端 , 從選擇器中可以獲取到所有的 通道 , 注意 屏蔽 服務器套接字通道發送本消息的客戶端對應的通道 ;


服務器連接監聽 : 當客戶端與服務器連接成功 , 即觸發注冊給 選擇器 ( Selector ) 的 服務器套接字通道 ( ServerSocketChannel ) 的 SelectionKey.OP_ACCEPT 事件 , 表示有客戶端連接服務器成功 , 用戶上線 ;


服務器斷開連接監聽 : 當服務器端與客戶端讀寫數據出現異常時 , 說明該客戶端離線 , 在異常處理代碼中可以判定某個客戶端離線 ;



1 . 服務器套接字通道 : 調用 open 靜態方法創建服務器套接字通道 , 并綁定 8888 端口 , 設置非阻塞網絡通信模式 ;

// 創建并配置 服務器套接字通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); serverSocketChannel.configureBlocking(false);

2 . 服務器端選擇器 : 調用 open 靜態方法獲取 選擇器 , 注冊之前創建的 服務器套接字通道 ;

// 獲取選擇器, 并注冊 服務器套接字通道 ServerSocketChannel selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

3 . 監聽事件 : 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數 ; 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中 ;

// 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數 // 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中 // 下面開始遍歷上述 selectedKeys 集合 try {int eventTriggerCount = selector.select(); } catch (IOException e) {e.printStackTrace(); }

4 . 處理客戶端連接事件 : 接受客戶端連接 , 獲取 網絡套接字通道 ( SocketChannel ) , 并注冊給 選擇器 ( Selector ) , 監聽 SelectionKey.OP_READ 數據讀取事件 ;

// 客戶端連接服務器, 服務器端需要執行 accept 操作 if (key.isAcceptable()) {//創建通道 : 為該客戶端創建一個對應的 SocketChannel 通道//不等待 : 當前已經知道有客戶端連接服務器, 因此不需要阻塞等待//非阻塞方法 : ServerSocketChannel 的 accept() 是非阻塞的方法SocketChannel socketChannel = null;try {socketChannel = serverSocketChannel.accept();//如果 ServerSocketChannel 是非阻塞的, 這里的 SocketChannel 也要設置成非阻塞的//否則會報 java.nio.channels.IllegalBlockingModeException 異常socketChannel.configureBlocking(false);//注冊通道 : 將 SocketChannel 通道注冊給 選擇器 ( Selector )//關注事件 : 關注事件時讀取事件, 服務器端從該通道讀取數據//關聯緩沖區 :socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));System.out.println(String.format("用戶 %s 進入聊天室", socketChannel.getRemoteAddress()));} catch (IOException e) {e.printStackTrace();} }

5 . 處理客戶端消息轉發事件 :


① 讀取客戶端上傳的數據 : 通過 SelectionKey 獲取 通道緩沖區 , 使用 套接字通道 ( SocketChannel ) 讀取 緩沖區 ( ByteBuffer ) 中的數據 , 然后記錄顯示該數據 ;

// 獲取 通道 ( Channel ) : 通過 SelectionKey 獲取 SocketChannel socketChannel = (SocketChannel) key.channel(); // 獲取 緩沖區 ( Buffer ) : 獲取到 通道 ( Channel ) 關聯的 緩沖區 ( Buffer ) ByteBuffer byteBuffer = (ByteBuffer) key.attachment(); String remoteAddress = null; String message = null; try {// 讀取客戶端傳輸的數據int readCount = socketChannel.read(byteBuffer);byte[] messageBytes = new byte[readCount];byteBuffer.flip();byteBuffer.get(messageBytes);// 處理讀取的消息message = new String(messageBytes);//重置以便下次使用byteBuffer.flip();remoteAddress = socketChannel.getRemoteAddress().toString();System.out.println(String.format("%s : %s", remoteAddress, message)); } catch (IOException e) {//e.printStackTrace();// 如果此處出現異常, 說明該客戶端離線了, 服務器提示, 取消選擇器上的注冊信息, 關閉通道try {System.out.println( String.format("%s 用戶離線 !", socketChannel.getRemoteAddress()) );key.cancel();socketChannel.close();//繼續下一次循環continue;} catch (IOException ex) {ex.printStackTrace();} }

② 轉發給其它客戶端 :選擇器 ( Selector )keys 集合 中獲取所有注冊的通道 , 然后除 ServerSocketChannel發送本信息的 客戶端對應的 SocketChannel 通道 之外 , 其它所有的通道都轉發一份聊天信息 ;

// 向其它客戶端轉發消息, 發送消息的客戶端自己就不用再發送該消息了 // 遍歷所有注冊到 選擇器 Selector 的 SocketChannel Set<SelectionKey> selectionKeys = selector.keys(); for (SelectionKey selectionKey : selectionKeys) {// 獲取客戶端對應的 套接字通道// 這里不能強轉成 SocketChannel, 因為這里可能存在 ServerSocketChannelChannel channel = selectionKey.channel();// 將自己排除在外, 注意這里是地址對比, 就是這兩個類不能是同一個地址的類// 這個類的類型必須是 SocketChannel, 排除之前注冊的 ServerSocketChannel 干擾if (socketChannel != channel && channel instanceof SocketChannel) {// 將通道轉為 SocketChannel, 之后將字符串發送到客戶端SocketChannel clientSocketChannel = (SocketChannel) channel;// 寫出字符串到其它客戶端try {clientSocketChannel.write(ByteBuffer.wrap( ( remoteAddress + " : " + message ).getBytes()));} catch (IOException e) {//e.printStackTrace();// 如果此處出現異常, 說明該客戶端離線了, 服務器提示, 取消選擇器上的注冊信息, 關閉通道try {System.out.println( String.format("%s 用戶離線 !", clientSocketChannel.getRemoteAddress()) );selectionKey.cancel();clientSocketChannel.close();} catch (IOException ex) {ex.printStackTrace();}}} }



三、 NIO 聊天室 客戶端 代碼分析



客戶端的連接與數據接收 : 客戶端的工作是連接服務器 , 得到與服務器通信的 套接字通道 ( SocketChannel ) , 注冊該通道到 選擇器 ( Selector ) , 監聽 SelectionKey.OP_READ 讀取數據事件 , 接收到數據后顯示即可 ;



1 . 連接服務器 : 連接服務器 , 并設置網絡通信非阻塞模式 ;

// 創建并配置 服務器套接字通道 ServerSocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(SERVER_ADDRESS, PORT)); socketChannel.configureBlocking(false);

2 . 獲取選擇器并注冊通道 : 獲取 選擇器 ( Selector ) , 并將 套接字通道 ( SocketChannel ) 注冊給該選擇器 ;

// 獲取選擇器, 并注冊 服務器套接字通道 ServerSocketChannel selector = Selector.open(); //注冊通道 : 將 SocketChannel 通道注冊給 選擇器 ( Selector ) //關注事件 : 關注事件時讀取事件, 服務器端從該通道讀取數據 //關聯緩沖區 : socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));

3 . 監聽服務器端下發的消息 : 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數 ; 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中 ;

// 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數 // 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中 // 下面開始遍歷上述 selectedKeys 集合 try {int eventTriggerCount = selector.select(); } catch (IOException e) {e.printStackTrace(); }

4 . 處理服務器端發送的數據 : 如果監聽到服務器下發數據 , 開始遍歷當前觸發事件的通道 , 調用該通道讀取數據到緩沖區 , 之后顯示該數據 ;

// 處理事件集合 : // 獲取當前發生的事件的 SelectionKey 集合, 通過 SelectionKey 可以獲取對應的 通道 Set<SelectionKey> keys = selector.selectedKeys(); // 使用迭代器迭代, 涉及到刪除操作 Iterator<SelectionKey> keyIterator = keys.iterator(); while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 根據 SelectionKey 的事件類型, 處理對應通道的業務邏輯// 客戶端寫出數據到服務器端, 服務器端需要讀取數據if (key.isReadable()) {// 獲取 通道 ( Channel ) : 通過 SelectionKey 獲取SocketChannel socketChannel = (SocketChannel) key.channel();// 獲取 緩沖區 ( Buffer ) : 獲取到 通道 ( Channel ) 關聯的 緩沖區 ( Buffer )ByteBuffer byteBuffer = (ByteBuffer) key.attachment();String message = null;try {// 讀取客戶端傳輸的數據int readCount = socketChannel.read(byteBuffer);byte[] messageBytes = new byte[readCount];byteBuffer.flip();byteBuffer.get(messageBytes);// 處理讀取的消息message = new String(messageBytes);byteBuffer.flip();System.out.println(String.format(message));} catch (IOException e) {//e.printStackTrace();// 客戶端連接斷開key.cancel();try {socketChannel.close();} catch (IOException ex) {ex.printStackTrace();}}// try}// if (key.isReadable())



四、 NIO 聊天室 服務器端 完整代碼



package kim.hsl.nio.chat;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; import java.util.Set;/*** 聊天室服務器端** @author hsl* @date 2020-05-29 17:24*/ public class Server {/*** 服務器監聽的端口號*/public static final int PORT = 8888;/*** 監聽 ServerSocketChannel 通道和各個客戶端對應的 SocketChannel 通道*/private Selector selector;/*** 服務器端的套接字通道, 相當于 BIO 中的 ServerSocket*/private ServerSocketChannel serverSocketChannel;/*** 初始化服務器相關操作*/public Server() {initServerSocketChannelAndSelector();}/*** 初始化 服務器套接字通道 和*/private void initServerSocketChannelAndSelector() {try {// 創建并配置 服務器套接字通道 ServerSocketChannelserverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(PORT));serverSocketChannel.configureBlocking(false);// 獲取選擇器, 并注冊 服務器套接字通道 ServerSocketChannelselector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);} catch (IOException e) {e.printStackTrace();}}/*** Selector 開始執行 監聽工作*/private void selectorStartSelectOperation() {System.out.println("服務器端啟動監聽 :");while (true) {// 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數// 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中// 下面開始遍歷上述 selectedKeys 集合try {int eventTriggerCount = selector.select();} catch (IOException e) {e.printStackTrace();}// 當前狀態說明 :// 如果能執行到該位置, 說明 selector.select() 方法返回值大于 0// 當前有 1 個或多個事件觸發, 下面就是處理事件的邏輯// 處理事件集合 :// 獲取當前發生的事件的 SelectionKey 集合, 通過 SelectionKey 可以獲取對應的 通道Set<SelectionKey> keys = selector.selectedKeys();// 使用迭代器迭代, 涉及到刪除操作Iterator<SelectionKey> keyIterator = keys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 根據 SelectionKey 的事件類型, 處理對應通道的業務邏輯// 客戶端連接服務器, 服務器端需要執行 accept 操作if (key.isAcceptable()) {//創建通道 : 為該客戶端創建一個對應的 SocketChannel 通道//不等待 : 當前已經知道有客戶端連接服務器, 因此不需要阻塞等待//非阻塞方法 : ServerSocketChannel 的 accept() 是非阻塞的方法SocketChannel socketChannel = null;try {socketChannel = serverSocketChannel.accept();//如果 ServerSocketChannel 是非阻塞的, 這里的 SocketChannel 也要設置成非阻塞的//否則會報 java.nio.channels.IllegalBlockingModeException 異常socketChannel.configureBlocking(false);//注冊通道 : 將 SocketChannel 通道注冊給 選擇器 ( Selector )//關注事件 : 關注事件時讀取事件, 服務器端從該通道讀取數據//關聯緩沖區 :socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));System.out.println(String.format("用戶 %s 進入聊天室", socketChannel.getRemoteAddress()));} catch (IOException e) {e.printStackTrace();}}// 客戶端寫出數據到服務器端, 服務器端需要讀取數據if (key.isReadable()) {// 獲取 通道 ( Channel ) : 通過 SelectionKey 獲取SocketChannel socketChannel = (SocketChannel) key.channel();// 獲取 緩沖區 ( Buffer ) : 獲取到 通道 ( Channel ) 關聯的 緩沖區 ( Buffer )ByteBuffer byteBuffer = (ByteBuffer) key.attachment();String remoteAddress = null;String message = null;try {// 讀取客戶端傳輸的數據int readCount = socketChannel.read(byteBuffer);byte[] messageBytes = new byte[readCount];byteBuffer.flip();byteBuffer.get(messageBytes);// 處理讀取的消息message = new String(messageBytes);//重置以便下次使用byteBuffer.flip();remoteAddress = socketChannel.getRemoteAddress().toString();System.out.println(String.format("%s : %s", remoteAddress, message));} catch (IOException e) {//e.printStackTrace();// 如果此處出現異常, 說明該客戶端離線了, 服務器提示, 取消選擇器上的注冊信息, 關閉通道try {System.out.println( String.format("%s 用戶離線 !", socketChannel.getRemoteAddress()) );key.cancel();socketChannel.close();//繼續下一次循環continue;} catch (IOException ex) {ex.printStackTrace();}}// 向其它客戶端轉發消息, 發送消息的客戶端自己就不用再發送該消息了// 遍歷所有注冊到 選擇器 Selector 的 SocketChannelSet<SelectionKey> selectionKeys = selector.keys();for (SelectionKey selectionKey : selectionKeys) {// 獲取客戶端對應的 套接字通道// 這里不能強轉成 SocketChannel, 因為這里可能存在 ServerSocketChannelChannel channel = selectionKey.channel();// 將自己排除在外, 注意這里是地址對比, 就是這兩個類不能是同一個地址的類// 這個類的類型必須是 SocketChannel, 排除之前注冊的 ServerSocketChannel 干擾if (socketChannel != channel && channel instanceof SocketChannel) {// 將通道轉為 SocketChannel, 之后將字符串發送到客戶端SocketChannel clientSocketChannel = (SocketChannel) channel;// 寫出字符串到其它客戶端try {clientSocketChannel.write(ByteBuffer.wrap( ( remoteAddress + " : " + message ).getBytes()));} catch (IOException e) {//e.printStackTrace();// 如果此處出現異常, 說明該客戶端離線了, 服務器提示, 取消選擇器上的注冊信息, 關閉通道try {System.out.println( String.format("%s 用戶離線 !", clientSocketChannel.getRemoteAddress()) );selectionKey.cancel();clientSocketChannel.close();} catch (IOException ex) {ex.printStackTrace();}}}}}// 處理完畢后, 當前的 SelectionKey 已經處理完畢// 從 Set 集合中移除該 SelectionKey// 防止重復處理keyIterator.remove();}}}public static void main(String[] args) {Server server = new Server();server.selectorStartSelectOperation();} }



五、 NIO 聊天室 客戶端 完整代碼



package kim.hsl.nio.chat;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; import java.util.Scanner; import java.util.Set;public class Client {/*** 服務器地址*/public final static String SERVER_ADDRESS = "127.0.0.1";/*** 服務器監聽的端口號*/public static final int PORT = 8888;/*** 監聽 SocketChannel 通道的 選擇器*/private Selector selector;/*** 服務器端的套接字通道, 相當于 BIO 中的 ServerSocket*/private SocketChannel socketChannel;public Client() {initClientSocketChannelAndSelector();}/*** 初始化 服務器套接字通道 和*/private void initClientSocketChannelAndSelector() {try {// 創建并配置 服務器套接字通道 ServerSocketChannelsocketChannel = SocketChannel.open(new InetSocketAddress(SERVER_ADDRESS, PORT));socketChannel.configureBlocking(false);// 獲取選擇器, 并注冊 服務器套接字通道 ServerSocketChannelselector = Selector.open();//注冊通道 : 將 SocketChannel 通道注冊給 選擇器 ( Selector )//關注事件 : 關注事件時讀取事件, 服務器端從該通道讀取數據//關聯緩沖區 :socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));} catch (IOException e) {e.printStackTrace();}}/*** 向服務器端發送消息* @param message*/public void sendMessageToServer(String message){try {socketChannel.write(ByteBuffer.wrap(message.getBytes()));} catch (IOException e) {e.printStackTrace();}}public void readMessageFromServer(){// 阻塞監聽, 如果有事件觸發, 返回觸發的事件個數// 被觸發的 SelectionKey 事件都存放到了 Set<SelectionKey> selectedKeys 集合中// 下面開始遍歷上述 selectedKeys 集合try {int eventTriggerCount = selector.select();} catch (IOException e) {e.printStackTrace();}// 當前狀態說明 :// 如果能執行到該位置, 說明 selector.select() 方法返回值大于 0// 當前有 1 個或多個事件觸發, 下面就是處理事件的邏輯// 處理事件集合 :// 獲取當前發生的事件的 SelectionKey 集合, 通過 SelectionKey 可以獲取對應的 通道Set<SelectionKey> keys = selector.selectedKeys();// 使用迭代器迭代, 涉及到刪除操作Iterator<SelectionKey> keyIterator = keys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 根據 SelectionKey 的事件類型, 處理對應通道的業務邏輯// 客戶端寫出數據到服務器端, 服務器端需要讀取數據if (key.isReadable()) {// 獲取 通道 ( Channel ) : 通過 SelectionKey 獲取SocketChannel socketChannel = (SocketChannel) key.channel();// 獲取 緩沖區 ( Buffer ) : 獲取到 通道 ( Channel ) 關聯的 緩沖區 ( Buffer )ByteBuffer byteBuffer = (ByteBuffer) key.attachment();String message = null;try {// 讀取客戶端傳輸的數據int readCount = socketChannel.read(byteBuffer);byte[] messageBytes = new byte[readCount];byteBuffer.flip();byteBuffer.get(messageBytes);// 處理讀取的消息message = new String(messageBytes);byteBuffer.flip();System.out.println(String.format(message));} catch (IOException e) {//e.printStackTrace();// 客戶端連接斷開key.cancel();try {socketChannel.close();} catch (IOException ex) {ex.printStackTrace();}}// try}// if (key.isReadable())// 處理完畢后, 當前的 SelectionKey 已經處理完畢// 從 Set 集合中移除該 SelectionKey// 防止重復處理keyIterator.remove();}}public static void main(String[] args) {Client client = new Client();// 接收服務器端數據線程new Thread(new Runnable() {@Overridepublic void run() {while (true){//不停地從服務器端讀取數據client.readMessageFromServer();}}}).start();Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()){String message = scanner.nextLine();client.sendMessageToServer(message);}} }



六、 NIO 聊天室 運行



按照如下步驟演示聊天室功能 ( 一定要按照順序執行 ) ;


1 . 服務器啟動 : 首先

2 . 設置客戶端多個 : 點擊下圖綠框中的下拉菜單 , 選擇 Edit Configuration , 彈出如下對話框 , 配置 Client 應用 , 勾選 Allow parallel run 選項 , 之后 Client 程序就可以運行多個 , 否則只能運行一個 ;

3 . 客戶端 111 連接 : 運行客戶端程序即可 ;

4 . 客戶端 222 連接 : 運行客戶端程序即可 ;

5 . 客戶端 333 連接 : 運行客戶端程序即可 ;

6 . 客戶端 222 發送消息 :

服務器顯示 : 客戶端 222 將消息發送給服務器 , 服務器顯示該消息 ;


客戶端 111 顯示 : 這是由服務器轉發的客戶端 222 發送的消息 , 客戶端 333 也收到該消息 ;

7 . 客戶端 222 退出 : 終止客戶端 222 程序 , 服務器端檢測到異常 , 就可以將客戶端 222 退出 ;

總結

以上是生活随笔為你收集整理的【Netty】NIO 网络编程 聊天室案例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 自拍偷拍欧美视频 | 国产丰满美女做爰 | 亚洲精品乱码久久久久 | 免费在线观看av片 | 亚洲天堂免费观看 | 欧美亚洲国产成人 | 久久黄网| 高清欧美性猛交xxxx黑人猛交 | 欧美瑟瑟| 永久免费观看av | 国产又粗又长又硬免费视频 | 一级少妇片 | 福利精品视频 | 免费国产一区二区 | 亚洲激情欧美 | 麻豆传媒视频入口 | 黄色网址视频在线观看 | 精品国产aⅴ一区二区三区东京热 | 久久久久久久免费 | 丰满少妇一区二区 | 色人阁视频 | 欧美三级黄色 | 天天插天天干天天操 | 6080午夜| 中文字幕日本视频 | 韩日一级片 | 中国黄色1级片 | 日韩电影网址 | 亚州av片 | av收藏小四郎最新地址 | www日本com| 欧美v在线 | 少妇做爰免费视频播放 | 日本阿v视频在线观看 | 欧美日韩一区二区三区在线 | 亚洲人成小说 | 天码人妻一区二区三区在线看 | 四虎影院污 | 日韩欧美在线视频观看 | 超碰2021| 黄色国产一级片 | 亚洲欧美激情在线观看 | 国产精品美女www | 爆操日本美女 | 第一色综合 | 成人日b视频 | 久久福利精品 | 欧美交换| 欧美女人一区二区 | 久久久久久久无码 | 伊人导航| 1024在线视频 | 国产不卡一 | 日本美女全裸 | 欧美日韩国产免费一区二区三区 | 男男做爰猛烈啪啪高 | 美女黄视频大全 | 亚洲综合免费观看高清完整版在线 | 中文字幕永久在线观看 | 超碰超碰在线 | 中国免费看的片 | 国产精品啊啊啊 | 亚洲无线看 | 国产日韩精品一区二区三区在线 | 狠狠干综合 | 久久精品国产免费看久久精品 | 黄网站色视频免费观看 | av免费播放 | 欧美亚洲国产成人 | 亚洲视频自拍 | 国产精品入口66mio男同 | 色欲色香天天天综合网www | 九九超碰 | 国产精品三 | 欧美久草视频 | 毛片视频观看 | 久久日精品 | 亚洲人妻一区二区 | 久久国产精品久久国产精品 | 国产精品日日摸夜夜爽 | 国产成人精品一区二区在线小狼 | 日韩亚洲区 | 亚洲一区免费在线 | 日韩精品一二 | 小sao货大ji巴cao死你 | www.国产.com | 黄毛片在线观看 | 久久国产乱 | 日韩精品在线免费视频 | 久久久久人妻一区精品色欧美 | 女性爱爱视频 | 亚洲欧洲成人在线 | 97国产| 欧美九九视频 | 成人性生活免费视频 | 欧美xxxx视频| 天堂在线视频免费观看 | 欧美狠狠爱 | 亚洲天堂成人av |