国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

這樣講 Netty 中的心跳機制,還有誰不會?

共 35513字,需瀏覽 72分鐘

 ·

2021-06-22 15:59

?點擊“肉眼品世界”,回復666 加入交流群?

“置頂公眾號”,每天進步一點點


基礎

何為心跳

顧名思義, 所謂 心跳, 即在 TCP 長連接中, 客戶端和服務器之間定期發(fā)送的一種特殊的數(shù)據(jù)包, 通知對方自己還在線, 以確保 TCP 連接的有效性.

為什么需要心跳

因為網(wǎng)絡的不可靠性, 有可能在 TCP 保持長連接的過程中, 由于某些突發(fā)情況, 例如網(wǎng)線被拔出, 突然掉電等, 會造成服務器和客戶端的連接中斷. 在這些突發(fā)情況下, 如果恰好服務器和客戶端之間沒有交互的話, 那么它們是不能在短時間內(nèi)發(fā)現(xiàn)對方已經(jīng)掉線的. 為了解決這個問題, 我們就需要引入 心跳 機制.

心跳機制的工作原理是: 在服務器和客戶端之間一定時間內(nèi)沒有數(shù)據(jù)交互時, 即處于 idle 狀態(tài)時, 客戶端或服務器會發(fā)送一個特殊的數(shù)據(jù)包給對方, 當接收方收到這個數(shù)據(jù)報文后, 也立即發(fā)送一個特殊的數(shù)據(jù)報文, 回應發(fā)送方, 此即一個 PING-PONG 交互. 自然地, 當某一端收到心跳消息后, 就知道了對方仍然在線, 這就確保 TCP 連接的有效性.

如何實現(xiàn)心跳

我們可以通過兩種方式實現(xiàn)心跳機制:

  • 使用 TCP 協(xié)議層面的 keepalive 機制.
  • 在應用層上實現(xiàn)自定義的心跳機制.

雖然在 TCP 協(xié)議層面上, 提供了 keepalive ?;顧C制, 但是使用它有幾個缺點:

  1. 它不是 TCP 的標準協(xié)議, 并且是默認關閉的.
  2. TCP keepalive 機制依賴于操作系統(tǒng)的實現(xiàn), 默認的 keepalive 心跳時間是 兩個小時, 并且對 keepalive 的修改需要系統(tǒng)調(diào)用(或者修改系統(tǒng)配置), 靈活性不夠.
  3. TCP keepalive 與 TCP 協(xié)議綁定, 因此如果需要更換為 UDP 協(xié)議時, keepalive 機制就失效了.

雖然使用 TCP 層面的 keepalive 機制比自定義的應用層心跳機制節(jié)省流量, 但是基于上面的幾點缺點, 一般的實踐中, 人們大多數(shù)都是選擇在應用層上實現(xiàn)自定義的心跳.

既然如此, 那么我們就來大致看看在在 Netty 中是怎么實現(xiàn)心跳的吧. 在 Netty 中, 實現(xiàn)心跳機制的關鍵是 IdleStateHandler, 它可以對一個 Channel 的 讀/寫設置定時器, 當 Channel 在一定事件間隔內(nèi)沒有數(shù)據(jù)交互時(即處于 idle 狀態(tài)), 就會觸發(fā)指定的事件.

使用 Netty 實現(xiàn)心跳

上面我們提到了, 在 Netty 中, 實現(xiàn)心跳機制的關鍵是 IdleStateHandler, 那么這個 Handler 如何使用呢? 我們來看看它的構造器:

public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
    this((long)readerIdleTimeSeconds, (long)writerIdleTimeSeconds, (long)allIdleTimeSeconds, TimeUnit.SECONDS);
}

實例化一個 IdleStateHandler 需要提供三個參數(shù):

  • readerIdleTimeSeconds, 讀超時. 即當在指定的時間間隔內(nèi)沒有從 Channel 讀取到數(shù)據(jù)時, 會觸發(fā)一個 READER_IDLE 的 IdleStateEvent 事件.
  • writerIdleTimeSeconds, 寫超時. 即當在指定的時間間隔內(nèi)沒有數(shù)據(jù)寫入到 Channel 時, 會觸發(fā)一個 WRITER_IDLE 的 IdleStateEvent 事件.
  • allIdleTimeSeconds, 讀/寫超時. 即當在指定的時間間隔內(nèi)沒有讀或?qū)懖僮鲿r, 會觸發(fā)一個 ALL_IDLE 的 IdleStateEvent 事件.

為了展示具體的 IdleStateHandler 實現(xiàn)的心跳機制, 下面我們來構造一個具體的EchoServer 的例子, 這個例子的行為如下:

  1. 在這個例子中, 客戶端和服務器通過 TCP 長連接進行通信.
  2. TCP 通信的報文格式是:
+--------+-----+---------------+ 
| Length |Type |   Content     |
|   17   |  1  |"HELLO, WORLD" |
+--------+-----+---------------+
  1. 客戶端每隔一個隨機的時間后, 向服務器發(fā)送消息, 服務器收到消息后, 立即將收到的消息原封不動地回復給客戶端.
  2. 若客戶端在指定的時間間隔內(nèi)沒有讀/寫操作, 則客戶端會自動向服務器發(fā)送一個 PING 心跳, 服務器收到 PING 心跳消息時, 需要回復一個 PONG 消息.

通用部分

根據(jù)上面定義的行為, 我們接下來實現(xiàn)心跳的通用部分 CustomHeartbeatHandler:

/**
 * @author xiongyongshun
 * @version 1.0
 */

public abstract class CustomHeartbeatHandler extends SimpleChannelInboundHandler<ByteBuf{
    public static final byte PING_MSG = 1;
    public static final byte PONG_MSG = 2;
    public static final byte CUSTOM_MSG = 3;
    protected String name;
    private int heartbeatCount = 0;

    public CustomHeartbeatHandler(String name) {
        this.name = name;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, ByteBuf byteBuf) throws Exception {
        if (byteBuf.getByte(4) == PING_MSG) {
            sendPongMsg(context);
        } else if (byteBuf.getByte(4) == PONG_MSG){
            System.out.println(name + " get pong msg from " + context.channel().remoteAddress());
        } else {
            handleData(context, byteBuf);
        }
    }

    protected void sendPingMsg(ChannelHandlerContext context) {
        ByteBuf buf = context.alloc().buffer(5);
        buf.writeInt(5);
        buf.writeByte(PING_MSG);
        context.writeAndFlush(buf);
        heartbeatCount++;
        System.out.println(name + " sent ping msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
    }

    private void sendPongMsg(ChannelHandlerContext context) {
        ByteBuf buf = context.alloc().buffer(5);
        buf.writeInt(5);
        buf.writeByte(PONG_MSG);
        context.channel().writeAndFlush(buf);
        heartbeatCount++;
        System.out.println(name + " sent pong msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
    }

    protected abstract void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf);

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // IdleStateHandler 所產(chǎn)生的 IdleStateEvent 的處理邏輯.
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case READER_IDLE:
                    handleReaderIdle(ctx);
                    break;
                case WRITER_IDLE:
                    handleWriterIdle(ctx);
                    break;
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("---" + ctx.channel().remoteAddress() + " is active---");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("---" + ctx.channel().remoteAddress() + " is inactive---");
    }

    protected void handleReaderIdle(ChannelHandlerContext ctx) {
        System.err.println("---READER_IDLE---");
    }

    protected void handleWriterIdle(ChannelHandlerContext ctx) {
        System.err.println("---WRITER_IDLE---");
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
        System.err.println("---ALL_IDLE---");
    }
}

類 CustomHeartbeatHandler 負責心跳的發(fā)送和接收, 我們接下來詳細地分析一下它的作用. 我們在前面提到, IdleStateHandler 是實現(xiàn)心跳的關鍵, 它會根據(jù)不同的 IO idle 類型來產(chǎn)生不同的 IdleStateEvent 事件, 而這個事件的捕獲, 其實就是在 userEventTriggered 方法中實現(xiàn)的.

我們來看看 CustomHeartbeatHandler.userEventTriggered 的具體實現(xiàn):

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof IdleStateEvent) {
        IdleStateEvent e = (IdleStateEvent) evt;
        switch (e.state()) {
            case READER_IDLE:
                handleReaderIdle(ctx);
                break;
            case WRITER_IDLE:
                handleWriterIdle(ctx);
                break;
            case ALL_IDLE:
                handleAllIdle(ctx);
                break;
            default:
                break;
        }
    }
}

在 userEventTriggered 中, 根據(jù) IdleStateEvent 的 state() 的不同, 而進行不同的處理. 例如如果是讀取數(shù)據(jù) idle, 則 e.state() == READER_IDLE, 因此就調(diào)用 handleReaderIdle 來處理它.

CustomHeartbeatHandler 提供了三個 idle 處理方法: handleReaderIdle, handleWriterIdle, handleAllIdle, 這三個方法目前只有默認的實現(xiàn), 它需要在子類中進行重寫, 現(xiàn)在我們暫時略過它們, 在具體的客戶端和服務器的實現(xiàn)部分時再來看它們.

知道了這一點后, 我們接下來看看數(shù)據(jù)處理部分:

@Override
protected void channelRead0(ChannelHandlerContext context, ByteBuf byteBuf) throws Exception {
    if (byteBuf.getByte(4) == PING_MSG) {
        sendPongMsg(context);
    } else if (byteBuf.getByte(4) == PONG_MSG){
        System.out.println(name + " get pong msg from " + context.channel().remoteAddress());
    } else {
        handleData(context, byteBuf);
    }
}

CustomHeartbeatHandler.channelRead0 中, 我們首先根據(jù)報文協(xié)議:

+--------+-----+---------------+ 
| Length |Type |   Content     |
|   17   |  1  |"HELLO, WORLD" |
+--------+-----+---------------+

來判斷當前的報文類型, 如果是 PING_MSG 則表示是服務器收到客戶端的 PING 消息, 此時服務器需要回復一個 PONG 消息, 其消息類型是 PONG_MSG.

扔報文類型是 PONG_MSG, 則表示是客戶端收到服務器發(fā)送的 PONG 消息, 此時打印一個 log 即可.

客戶端部分

客戶端初始化

public class Client {
    public static void main(String[] args) {
        NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
        Random random = new Random(System.currentTimeMillis());
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap
                    .group(workGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() 
{
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new IdleStateHandler(005));
                            p.addLast(new LengthFieldBasedFrameDecoder(102404, -40));
                            p.addLast(new ClientHandler());
                        }
                    });

            Channel ch = bootstrap.remoteAddress("127.0.0.1"12345).connect().sync().channel();
            for (int i = 0; i < 10; i++) {
                String content = "client msg " + i;
                ByteBuf buf = ch.alloc().buffer();
                buf.writeInt(5 + content.getBytes().length);
                buf.writeByte(CustomHeartbeatHandler.CUSTOM_MSG);
                buf.writeBytes(content.getBytes());
                ch.writeAndFlush(buf);

                Thread.sleep(random.nextInt(20000));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            workGroup.shutdownGracefully();
        }
    }
}

上面的代碼是 Netty 的客戶端端的初始化代碼, 使用過 Netty 的朋友對這個代碼應該不會陌生. 別的部分我們就不再贅述, 我們來看看 ChannelInitializer.initChannel 部分即可:

.handler(new ChannelInitializer<SocketChannel>() {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline p = socketChannel.pipeline();
        p.addLast(new IdleStateHandler(005));
        p.addLast(new LengthFieldBasedFrameDecoder(102404, -40));
        p.addLast(new ClientHandler());
    }
});

我們給 pipeline 添加了三個 Handler, IdleStateHandler 這個 handler 是心跳機制的核心, 我們?yōu)榭蛻舳硕嗽O置了讀寫 idle 超時, 時間間隔是5s, 即如果客戶端在間隔 5s 后都沒有收到服務器的消息或向服務器發(fā)送消息, 則產(chǎn)生 ALL_IDLE 事件.

接下來我們添加了 LengthFieldBasedFrameDecoder, 它是負責解析我們的 TCP 報文, 因為和本文的目的無關, 因此這里不詳細展開.

最后一個 Handler 是 ClientHandler, 它繼承于 CustomHeartbeatHandler, 是我們處理業(yè)務邏輯部分.

客戶端 Handler

public class ClientHandler extends CustomHeartbeatHandler {
    public ClientHandler() {
        super("client");
    }

    @Override
    protected void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) {
        byte[] data = new byte[byteBuf.readableBytes() - 5];
        byteBuf.skipBytes(5);
        byteBuf.readBytes(data);
        String content = new String(data);
        System.out.println(name + " get content: " + content);
    }

    @Override
    protected void handleAllIdle(ChannelHandlerContext ctx) {
        super.handleAllIdle(ctx);
        sendPingMsg(ctx);
    }
}

ClientHandler 繼承于 CustomHeartbeatHandler, 它重寫了兩個方法, 一個是 handleData, 在這里面實現(xiàn) 僅僅打印收到的消息.

第二個重寫的方法是 handleAllIdle. 我們在前面提到, 客戶端負責發(fā)送心跳的 PING 消息, 當客戶端產(chǎn)生一個 ALL_IDLE 事件后, 會導致父類的 CustomHeartbeatHandler.userEventTriggered 調(diào)用, 而 userEventTriggered 中會根據(jù) e.state() 來調(diào)用不同的方法, 因此最后調(diào)用的是 ClientHandler.handleAllIdle, 在這個方法中, 客戶端調(diào)用 sendPingMsg 向服務器發(fā)送一個 PING 消息.

服務器部分

服務器初始化

public class Server {
    public static void main(String[] args) {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap
                    .group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() 
{
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new IdleStateHandler(1000));
                            p.addLast(new LengthFieldBasedFrameDecoder(102404, -40));
                            p.addLast(new ServerHandler());
                        }
                    });

            Channel ch = bootstrap.bind(12345).sync().channel();
            ch.closeFuture().sync();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

服務器的初始化部分也沒有什么好說的, 它也和客戶端的初始化一樣, 為 pipeline 添加了三個 Handler.

服務器 Handler

public class ServerHandler extends CustomHeartbeatHandler {
    public ServerHandler() {
        super("server");
    }

    @Override
    protected void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf buf) {
        byte[] data = new byte[buf.readableBytes() - 5];
        ByteBuf responseBuf = Unpooled.copiedBuffer(buf);
        buf.skipBytes(5);
        buf.readBytes(data);
        String content = new String(data);
        System.out.println(name + " get content: " + content);
        channelHandlerContext.write(responseBuf);
    }

    @Override
    protected void handleReaderIdle(ChannelHandlerContext ctx) {
        super.handleReaderIdle(ctx);
        System.err.println("---client " + ctx.channel().remoteAddress().toString() + " reader timeout, close it---");
        ctx.close();
    }
}

ServerHandler 繼承于 CustomHeartbeatHandler, 它重寫了兩個方法, 一個是 handleData, 在這里面實現(xiàn) EchoServer 的功能: 即收到客戶端的消息后, 立即原封不動地將消息回復給客戶端.

第二個重寫的方法是 handleReaderIdle, 因為服務器僅僅對客戶端的讀 idle 感興趣, 因此只重新了這個方法. 若服務器在指定時間后沒有收到客戶端的消息, 則會觸發(fā) READER_IDLE 消息, 進而會調(diào)用 handleReaderIdle 這個方法.

我們在前面提到, 客戶端負責發(fā)送心跳的 PING 消息, 并且服務器的 READER_IDLE 的超時時間是客戶端發(fā)送 PING 消息的間隔的兩倍, 因此當服務器 READER_IDLE 觸發(fā)時, 就可以確定是客戶端已經(jīng)掉線了, 因此服務器直接關閉客戶端連接即可.

總結(jié)

  1. 使用 Netty 實現(xiàn)心跳機制的關鍵就是利用 IdleStateHandler 來產(chǎn)生對應的 idle 事件.
  2. 一般是客戶端負責發(fā)送心跳的 PING 消息, 因此客戶端注意關注 ALL_IDLE 事件, 在這個事件觸發(fā)后, 客戶端需要向服務器發(fā)送 PING 消息, 告訴服務器"我還存活著".
  3. 服務器是接收客戶端的 PING 消息的, 因此服務器關注的是 READER_IDLE 事件, 并且服務器的 READER_IDLE 間隔需要比客戶端的 ALL_IDLE 事件間隔大(例如客戶端ALL_IDLE 是5s 沒有讀寫時觸發(fā), 因此服務器的 READER_IDLE 可以設置為10s)
  4. 當服務器收到客戶端的 PING 消息時, 會發(fā)送一個 PONG 消息作為回復. 一個 PING-PONG 消息對就是一個心跳交互.

實現(xiàn)客戶端的斷線重連

public class Client {
    private NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
    private Channel channel;
    private Bootstrap bootstrap;

    public static void main(String[] args) throws Exception {
        Client client = new Client();
        client.start();
        client.sendData();
    }

    public void sendData() throws Exception {
        Random random = new Random(System.currentTimeMillis());
        for (int i = 0; i < 10000; i++) {
            if (channel != null && channel.isActive()) {
                String content = "client msg " + i;
                ByteBuf buf = channel.alloc().buffer(5 + content.getBytes().length);
                buf.writeInt(5 + content.getBytes().length);
                buf.writeByte(CustomHeartbeatHandler.CUSTOM_MSG);
                buf.writeBytes(content.getBytes());
                channel.writeAndFlush(buf);
            }

            Thread.sleep(random.nextInt(20000));
        }
    }

    public void start() {
        try {
            bootstrap = new Bootstrap();
            bootstrap
                    .group(workGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() 
{
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new IdleStateHandler(005));
                            p.addLast(new LengthFieldBasedFrameDecoder(102404, -40));
                            p.addLast(new ClientHandler(Client.this));
                        }
                    });
            doConnect();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected void doConnect() {
        if (channel != null && channel.isActive()) {
            return;
        }

        ChannelFuture future = bootstrap.connect("127.0.0.1"12345);

        future.addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture futureListener) throws Exception {
                if (futureListener.isSuccess()) {
                    channel = futureListener.channel();
                    System.out.println("Connect to server successfully!");
                } else {
                    System.out.println("Failed to connect to server, try connect after 10s");

                    futureListener.channel().eventLoop().schedule(new Runnable() {
                        @Override
                        public void run() {
                            doConnect();
                        }
                    }, 10, TimeUnit.SECONDS);
                }
            }
        });
    }

}

上面的代碼中, 我們抽象出 doConnect 方法, 它負責客戶端和服務器的 TCP 連接的建立, 并且當 TCP 連接失敗時, doConnect 會 通過 channel().eventLoop().schedule 來延時10s 后嘗試重新連接.

客戶端 Handler

public class ClientHandler extends CustomHeartbeatHandler {
    private Client client;
    public ClientHandler(Client client) {
        super("client");
        this.client = client;
    }

    @Override
    protected void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) {
        byte[] data = new byte[byteBuf.readableBytes() - 5];
        byteBuf.skipBytes(5);
        byteBuf.readBytes(data);
        String content = new String(data);
        System.out.println(name + " get content: " + content);
    }

    @Override
    protected void handleAllIdle(ChannelHandlerContext ctx) {
        super.handleAllIdle(ctx);
        sendPingMsg(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        client.doConnect();
    }
}

斷線重連的關鍵一點是檢測連接是否已經(jīng)斷開. 因此我們改寫了 ClientHandler, 重寫了 channelInactive 方法. 當 TCP 連接斷開時, 會回調(diào) channelInactive 方法, 因此我們在這個方法中調(diào)用 client.doConnect() 來進行重連。

作者:永順

https://urlify.cn/FjyQZf


推薦閱讀:

世界的真實格局分析,地球人類社會底層運行原理

企業(yè)IT技術架構規(guī)劃方案

論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

【中臺實踐】華為大數(shù)據(jù)中臺架構分享.pdf

華為的數(shù)字化轉(zhuǎn)型方法論

華為如何實施數(shù)字化轉(zhuǎn)型(附PPT)

超詳細280頁Docker實戰(zhàn)文檔!開放下載

華為大數(shù)據(jù)解決方案(PPT)

瀏覽 31
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 免费无码国产在线观看快色| 国产在线欧美在线| 婷婷激情久久| 精品无码一区二区三区的天堂| 无码精品黑人| 国产高清精品无码| 99国产精品| 欧美一级AA大片免费看视频 | 99天天视频| 亚洲免费精品视频| 欧美日韩黄色| 91成人| 天天天天天天天天操| 91亚洲一区| 黑人无码一二三四五区| 97毛片| 操逼在线免费观看| 天堂中文资源库| 国内精品久久久久久久久久变脸| 狠狠色噜噜狠狠狠7777米奇网 | 国产在线激情视频| 91亚洲国产成人精品一区| 看肏屄视频| 一区黄片| 日本成人黄色| 九九中文字幕| 大香蕉国产| 色婷婷电影| 免费黄色成人| 免费欧美三级片| 北条麻妃无码| 亚洲AV第二区国产精品| 精品视频国产| 看一级黄色片| 亚洲AV无码成人专区| 精品视频免费在线| 欧美日韩一区二区三区四区五区六区 | 欧美mv日韩mv国产| 99精品在线播放| 影音先锋乱伦电影| 一本一道vs波多野结衣| 国产综合久久久777777| 丁香五月激情视频| 欧美老熟妇乱大交XXXXX| 91黑人| 大香蕉网伊人在线| 中文字幕+乱码+中文乱码视频在线观看 | 国产av二区| 黄色免费福利视频| 黄色资源在线观看| 操一区| 二区不卡| 欧美色图另类图片| 成人理论片| 人人操天天| 久热最新| 无码中文字幕高清| 91爱搞搞| 91久久爽久久爽爽久久片| 99久久婷婷国产综合精品hsex,亚| 俺也去也| 狠狠躁18三区二区一区免费人| 国产熟女一区| 免费AV影片| 97播播| 成人做爰黄级A片免费看土方| 搞搞网日本9| 国产特級黃色大片| 99国产精品| 91视频人妻| 另类图片亚洲色图| 亚洲免费成人网站| 国产亚洲99久久精品熟女| 亚州一级二级| 狠狠操一区| a级黄色视频免费观看| 久久人人操| 91免费观看视频| 色五月婷婷中文字幕| 久久午夜无码鲁丝片午夜精| 91人人妻人人澡人人爽| 2019天天干| av影音在线| 国产精品久久无码| 日本大香蕉伊人| 国产农村妇女精品一二区| 亚洲综合激情网| 色综合色综合色综合| 亚洲精品美女视频| 日韩综合区| 噜噜噜AV| 国产麻豆免费| 日本免费在线观看视频| 99精品一区二区| 思思精品在线| 色哟哟视频在线观看| 日韩AV无码电影| 日韩一级在线播放| 午夜无码精品一区二区三区99午| 99热在线免费| 国产亚洲中文字幕| www国产精品| 亚洲综合天堂| 人妻碰碰| 成人免费黄色| 污网站免费在线观看| 五十路av| 亚洲无码A片在线观看| 97超碰人妻| 九色PORNY国产成人| 青青草原在线| 性猛交AAAA片免费看蜜桃视频| 国产成人精品一区二区三区| 国产一二三四区| 久久视频精品| 国产欧美一区二区三区在线看蜜臀| 国产免费AV在线| 成年人黄色片| 俺去夜| 伊人大香蕉在线观看| 国产成人无码A片免费看| 四川BBBBBB搡BBBBB| 91艹逼| 日韩性爱A片| 人妻制服丝袜| 青青草原无码| 午夜福利免费| 大黑人荫蒂BBBBBBBBB| 亚洲无码专区在线观看| 免费成人黄色网址| 人妻无码一区二区三区摄像头| 欧美精品一二三区| 国产午夜无码福利视频| 成人777| 丁香五月天激情| 99re99| 久久午夜无码鲁片午夜精品男男 | 黄色综合网| 日本爽妇网| 人妻久久久| A级成人网站| 人人澡人人看| 免费看无码网站成人A片| 五月天网址| 强伦轩人妻一区二区三区最新版本更新内容 | 影音先锋乱伦电影| 亚洲色成人网站www永久四虎| 熟女3p| 中国12一13毛片| 亚洲黄色视频免费观看| 亚洲欧美日韩动漫| 伊人精品A片一区二区三区| 三个黑人猛躁我一晚上| 人人爱,人人操| 日韩毛片网| 免费成人毛片| 18禁网址| 俺来也俺去也www色| 亚洲精品一线| 91就去干| www.91熊猫成人网| 国产区欧美去区在线| 欧美黄色网址| 午夜理论片| 内射视频在线观看| 牛牛AV| 亚洲高清人妻| 91嫩草久久久久久久| 日韩av无码电影| 狠狠色噜噜狠狠狠7777| 黄色免费看视频| 国产亚洲一区二区三区| 高清无码视频在线播放| 亚洲成人黄色| 无码成人视频| 丁香五月伊人| 日韩欧美小电影| 国产九九在线视频| 亚洲AV无码乱码国产精品蜜芽| 无码操| 天天爱天天射| 91麻豆福利在线观看| 人人摸人人操人人爽| 国产精品午夜成人免费| 成人免费版欧美州| 黄色A片约| 国模一区二区三区| 黄片网站在线免费观看| 欧美AAA在线观看| 先锋影音麻豆| 91免费视频在线| 国产一级视频| 亚洲国产成人精品激情在线| 日本无码成人片在线播放| 夜夜骚av.一区二区三区四区| 无码AV免费观看| 亚洲欧美精品在线| 四川少妇搡bbbbb搡多人| 屌国产精品| 黄色免费福利视频| 久久久久亚洲AV无码网影音先锋 | 黄色一级片免费看| 亚洲高清无码免费| 特猛特黄AAAAAA片| 北京熟妇搡BBBB搡BBBB电影| 三级片免费网址| 欧美成人性爱网站| 夜夜操天天干| 亚洲综合免费观看高清完整版在线 | 男人天堂视频在线| 国产传媒_色哟哟| 国产欧美一区二区三区四区 | 偷窥丶亚洲丶熟女| 综合合一品道| 逼特逼视频在线| 欧美精品一二三| 精品九九| 香蕉国产精品| 亚洲精品久久久久毛片A级绿茶 | 亚洲精品秘一区二区三区蜜桃久 | 国产av二区| 18禁av在线| 蜜臀99久久精品久久久久久软件 | 97人人色| 国产av黄色| 特黄视频| 五月天啪啪视频| 日本理论片一道本| 99精品免费| 国产A√| 成人免费A片视频| 午夜三级无码| 91ThePorn国产在线观看| 女人天堂av| 亚洲国产操逼| 91久久久久久久久久久久18| 亚洲高清无码免费观看| 亚洲无码视频播放| 黄色免费高清视频| 在线观看日韩欧美| 欧美性爱视频在线观看| 91香蕉视频18| 精品无码一区二区三区四区五区| 国产操逼大片| 日韩免费无码视频| 懂色午夜福利一区二区三区| 亚洲videos| 99久久99久久精品免费看小说。| 欧美日韩国产一区二区| 艹逼电影| 大色AV| 成人精品无码免费视频| 青青青操| 久久久无码AV| 欧美人妻日韩精品| 豆花成人视频| 俺去啦俺也去| 国产青草视频| 日本a级视频| 一级操逼黄色视频| 伊人大香蕉网站| 91足浴店按摩漂亮少妇| 欧美一区二区在线观看| 久久精品无码一区二区无码性色| 蜜桃传媒av| 国产十八岁在线观看| 中文字幕88页| 成人亚洲av| 亚洲人在线| 91性爱小视频| 一区电影网| 国产精品一区二区性色AV| 国产一级视频| 久久亚洲一区| jjzz国产| 亚洲免费在线视频| 欧美色图俺去了| 视色影院| 亚洲天堂无码a| 国产成人h| 91成人精品一区二区| 日韩一级免费| 男人天堂无码视频| 91精品国产麻豆国产自产在线| 91麻豆免费视频网站| 中文免费高清在线| 中文有码视频| 日日射人妻| 新超碰97| 欧美老熟妇乱大交XXXXX| 99精品视频播放| 色呦呦视频在线观看| 五月丁香大香蕉| 一级艹逼| 熟妇熟女一区二区三区| 欧美人操逼| v天堂在线观看| 国产理论片在线观看| 嫩BBB嫩BBB嫩BBBn嫩| 青青大香蕉| 国产精品视频网站| 国产码在线成人网站| 国产精品囯产三级囯产AV野外| 丰满人妻精品一区二区在线 | 最新一区二区| 在线观看免费a片| 亚洲国产婷婷香蕉A片| 韩国色情中文字幕| 激情五月婷婷综合| 九色PORNY自拍视频| 三级不卡视频| 欧美一区二区三区不卡| A片黄色电影| 成人免费视频性爱| 日本黄色电影在线观看| 亚洲AV第二区国产精品| 神马午夜激情| 亚洲国产精品成人久久蜜臀| 人人操人人看人人摸| 91最新地址| 久久思思热| 久久久久亚洲AV无码专区成人| 欧美A在线| 黃色A片一級二級三級免費久久久| 无码电影免费观看| 国产精品久久久久毛片SUV| aV无码av天天aV天天爽第一| AAA三级片| 最新免费毛片| 18禁无码永久免费网站大全| 黄色一级网站| 久久AA| 中文字幕第一区| 无码欧美精品一区二区| 日本親子亂子倫XXXX50路| 败火老熟女ThePorn视频| 在线操B| 欧美一区二区三区婷婷五月| 欧美三级无码| 欧美黄色一级视频| 国产黄片在线播放| 一本色道久久综合亚洲精品久久| 亚洲综合成人在线| 大香蕉久久久久| 日韩精品一区二区三免费视频| 在线国产中文字幕| 国产无套进入免费| 午夜91| 丁香五月在线视频| 91一起草高清资源| 图片区视频区小说区| 伊人视频网| 北条麻妃无码中文| 欧美后门菊门交4| 国产在线视频导航| 亚洲中文自拍| 亚洲区成人777777精品| 亚洲无码在线观看免费| 国产香蕉精品视频| 欧美日韩性爰视频| 亚洲精品一二三| 91熟女丰满原味| 91人妻人人澡人人爽精品| 亚洲女人天堂| yw视频在线观看| 99视频在线免费观看| 精品国产女人| 一区二区久久| av超碰在线| 久久三级视频| 婷婷狠狠爱| A片免费在线观看| 人人爽人人操人人| 高清无码免费视频| 毛片在线免费| 色欲影视插综合一区二区三区| www.丁香五月| 免费观看色情视频| 操逼电影网站| 欧美亚洲国产精品| 黄色av免费观看| 人妻精品电影| 成人亚洲A片V一区二区三区蜜月| 国产美女18毛片水真多| 91精品免费| 亚洲精品另类| 国精品伦一区一区三区有限公司 | 丝袜二区| 日本在线小视频| 免费观看黄色一级片| 亚洲视频中文| 久草视频2| 熟女人妻人蜜桃视频| 97人人干人人| 日韩AV大片| 日韩一级一级| 最新免费一区二区三区| 亚洲中文在线视频| 爱草在线| 天干天干天夜夜操| 天堂俺去俺来也www久久婷婷 | 午夜无码免费| 中文字幕日韩av| 亚洲国产成人av| AV在线精品| 欧美亚洲操逼视频| 欧美日皮视频| 成人先锋| 粉嫩一区| 一级片在线视频| 综合视频一区| 欧美日韩国产高清| A级免费视频| 99久久精品国产色欲| 骚逼无码| 操逼无码精品| 国产精品卡一卡二| 九色丨蝌蚪丨老版熟女| 国产成人秘免费观看一区二区三区| 国产一区二三区| 91香蕉视频在线| 69视频免费观看| 在线观看亚州| 成人做爰黄A片免费看直播室动漫| 国产欧美综合一区二区| 骚逼影院| 91av免费在线观看| 这里视频很精彩免费观看电视剧最新| 亚洲AV成人精品日韩在线播放| 特黄色A级片视频| 亚洲人妻中文字幕| 精品AV无码| 日韩精品影视| 日韩成人在线免费观看| 欧美成人精品三级网站| 超碰人人在线| 蜜臀久久99精品久久久兰草影视| 肉色超薄丝袜脚交一区二区| 伊人亚洲综合| 免费网站观看www在线观| 免费18蜜桃久久19| 激情五月天在线观看| 人妻体体内射精一区二区| 日屁视频| 韩国三级片在线| 懂色成人av影院| 国产日韩一区| 五月天婷婷综合网| 成人视频网站在线观看18| 免费日本黄色| 日韩日逼网站| 亚洲性爱电影| 特级西西444www精品视频| 成人在线视频一区| 成人网站视频在线观看| 99天天操| 精品国产成人| 黄色视频网站免费在线观看| 高清无码免费不卡| 国产精品女人精品久久久天天 | 国产精品日韩无码| 亚洲香蕉视频网站| 超碰人人干| 天天色天天色天天色| 精品国产免费无码久久噜噜噜AV | 久久婷婷五月综合伊人| 西西www444无码大胆| 你懂的在线播放| 99成人网站| 欧美性爱高清| 豆花成人视频| 91AV视频在线| 日韩三级视频在线观看| 四川BBBB擦BBBB| 9797色色| 日韩黄色片在线观看| 日韩免费高清| 亚洲综合社区| 天天看天天爽| 国产乱码在线| 亚洲第一页在线| 91亚洲精选| 国产成人tv| 亚洲少妇视频| 国产精品久久无码| 亚洲中文免费观看| 女人的天堂AV在线观看| 肏屄视频免费观看| 欧美久久久久久久| 日操操| 亚洲vs无码秘蜜桃少妇| 人妻黄色视频| 91人妻人人澡人人爽人人DVD| 久久久久久久| 欧美级毛片一夜| 99综合久久| 日韩在线观看视频免费| 亚洲视频第一页| 蜜臀av在线观看| 草草影院第一页YYCCC| 天天天日天天天操| 91国产爽黄在线| 亚洲成人在线无码| 精品久草| 黄色毛片,男人天堂| 极品少妇AV| 永久精品| 亚洲色成人中文字幕在线| 69av在线观看| 337p大胆色噜噜噜噜噜| 99久re热视频精品98| 超碰天天射| 九九久久精品| 欧美日本在线观看| 伊人五月天| 狼友视频免费观看| 日韩AV在线免费观看| 日韩欧美二区| 婷婷高清无码| 日本大香蕉在线视频| 天天爽夜夜爽夜夜爽精品视频| 日韩1页| 无码入口| 中文字幕+乱码+中文字幕一区| 91视频在线观看| 久久女人视频| 国产在线视频91| 国产乱子伦一区二区三| 亚洲三区视频| 天堂中文字幕在线观看| 国产aⅴ激情无码久久久无码| 国产一级AV免费观看| 中文亚洲精品字幕电影| 99国产精品| 国产高清自拍视频| 日韩人妻码一区二区三区| 超碰97人人爱| 抽插逼| 国产天堂| 日日夜夜av| 69AV视频在线观看| 天天草av| 天天干在线观看视频| 亚洲男人天堂| 婷婷丁香激情五月天| 西西人体444rt高清大胆模特 | 久久久亚洲无码精品| 97精品一区二区三区A片| 欧美精品在线免费观看| 午夜福利啪啪啪| 高清无码人妻| 精品自拍偷拍| 国产高清免费无码| 无码蜜桃一区二区| 成人久操| 99热| 五月婷婷在线视频| 看a网站| 嫩BBB| 黑人一区二区三区四区| 五月天婷婷在线播放视频免费观看 | 翔田千里av| 黄色小说视频网站| 国产成人欧美| 高清无码视频直接看| 亚洲日韩国产AV| 91人人澡| 国产91无码精品秘入口新欢| 1024国产| 亚洲不卡中文字幕| 色噜噜人妻av中文字幕| 激情五月天亚洲| 91av天堂| 三级无码| 国产成人秘免费观看一区二区三区| 精品乱子伦一区二区三区免费播成| 女生操逼网站| 成人一区视频| 中文字幕在线视频日本| 欧一美一伦一A片| 亚洲色色频| 亚洲高清免费视频| 97成人在线| 精品视频91| 成人无码日韩精品| 91看片看婬黄大片Videos | 操逼网站在线| 懂色成人av影院| 黄色视频在线观看网站| 亚洲骚逼| 日韩国产一区二区| 日韩在线视频中文字幕码无| 日韩成人av在线| 久久精品婷婷| 91人妻人人澡人人爽人人精品一| 久久日av| 辽宁模特张雪馨视频最新| 91香蕉在线| 九九色影院| 四虎欧美| 蜜桃av无码一区二区三区| NP玩烂了公用爽灌满视频播放| 99精品自拍| 色悠悠中文字幕| 欧美一级做| 五月欧美激情| 亚洲中文字幕在线观看视频网站| 青春草在线视频| 亚洲一级黄色| 日日夜夜av| 久久噜噜噜精品国产亚洲综合| 蜜臀av在线观看| 国产成人精品一区二| 亚洲观看黄色网| 玖玖爱这里只有精品| 黑人精品XXX一区一二区| 久9久9| 国内成人自拍| 一本到在线观看午夜剧场| 日韩人妻丰满无码区A片| 久久久91| AAA片| 欧美一级片在线| 伊人久久av| 九九热国产视频| 久久午夜电影| 久久这里精品| 九九综合网| 久久夜色精品国产噜噜亚洲AV| 4438黄色| 亚洲无码免费网站| 97免费在线观看视频| 成人综合大香蕉| 日韩AV免费网站| 天天色天天干天天| 伊人色色综合| 久久久97精品久久| 2025av中文字幕| 免费性爱视频| 无码高清在线| 青娱乐青青草| 99视频免费观看| 99人妻视频| 在线大香蕉| 欧美国产综合| 亚洲第一av| 大香蕉日逼| 奇米色色色| 先锋影音AV在线| 香蕉网址| 国产精品国产精品国产专区| 国产一级a毛一级a做免费图片| 91丨九色丨熟女丰满| 操天天| 麻豆久久久久| 成人小说一区二区三区| 国产亚洲欧美精品综合在线| 色三区| 日韩欧美手机在线| 日韩无码五月天| www.日本色| 欧美在线视频播放| 日韩精品一区二区在线观看| 黄色国产AV| 一级中国毛片| 成人小说一区二区三区| 国产嫩BBwBBw高潮| 一级一A片一a免费看| 欧美成人免费电影| 欧美日韩爱爱| 操操网| 麻豆午夜成人无码电影| 欧美黄色三级片| 色婷婷色99国产综合精品| 在线看黄网站| 成人国产在线观看| 亚洲高清在线观看视频| 日韩无码小电影| 婷婷五月天社区| 日韩黄色大片| 亚洲av影院| 综合婷婷| 欧美熟妇精品一二三区| 久久99久久99久久| 精品人妻一区二区三区四区| 国产一区二区三区成人| 看欧美黄片| 毛片学生妹| 成人性生交片无码免费看人| 日本精品视频在线| 操逼去| 成人精品福利| 苍井空无码在线观看| 欧美老女人操逼视频| 人妻精品无码| 国产精品国产三级国产专区53| 久操视频免费在线观看| 欧美成人免费A级在线观看| 农村老太HD肉HD| 岛国无码破解AV在线播放| 亚洲视频久久| 中文字幕日韩人妻在线| 日韩A级毛片| 免费无码成人片在线观看在线 | 国产卡一卡二在线观看| 91在线观看免费视频| 午夜xxx| 4438黄色| 老太色HD色老太HD-百度| 久久大屌| 亚洲精品成AV人片天堂无码| 99热电影| 国产主播福利| 香蕉久草| 亚洲三级无码| 操杨幂| 亚洲国产成人va| 手机在线一区| 亚洲美女网站免费观看网址| 国产一级片内射| 欧美国产一区二区| 91AV无码| 久操免费在线视频| 青草青视频| 久久密| 亚洲二区后入极品| 亚洲精品色色| 夜夜操狠狠操| 成人777777免费视频色| 亚洲国产欧美日韩在线| 亚洲在线大香蕉| 性亚洲| 亚洲资源网| 中文字幕婷婷| 老司机狠狠干| 欧美激情伊人| 亚洲欧美精品AAAAAA片| 成人做爱黄片| 麻豆一级| 五月天精品| 操逼在线看| а√最新版天堂中文在线| 久久免费观看视频| 韩日一级17c| 伊人蕉 | 色九月婷婷| 你懂得视频| 偷拍-91爱爱| 亚洲高清无码一区二区三区| xxxx国产| 久久密| 2016av天堂网| 免费观看黄色一级片| 久久精品女同亚洲女同13| 成人电影综合网| 麻豆国产91在线播放| 依人成人| 91免费在线| 瘦精品无码一区二区三区四区五区六区七区八区 | 亚洲一区中文字幕成人在线| 欧美一级黄片免费看| 丁香久久婷婷| 日产精品久久久一区二区| 亚洲国产成人91PORN| 69人妻人人澡人人爽人人精品| 亚洲免费视频观看| 亚洲都市激情| 狠狠做深爱婷婷久久综合一区| 就要操逼| 亚洲精品不卡| h片免费在线观看| 国产美女裸体网站| 免费AV黄色| 国内自拍欧美| 色色综合视频| 成人h在线观看| 最新中文字幕777私人在线| 青青草资源站| 超碰P| 北条麻妃在线一区二区| AV无码中文| 99这里只有精品视频| 一级黄色毛片| 青青热久| 超碰人| 久久久久久毛片| 国产精品福利视频| 欧美激情四射老司机| 日韩无码一区二区三| 色色操| 婷婷国产AV| 69视频网站| 久久伊人春色| 中文字幕在线视频日本| 日本一区不卡| 黄片视频在线免费观看| 人人爽人人爽| 国产欧美一| 久久久69| 国产小电影在线| 一级片在线观看视频| 青青草免费在线视| 日韩毛片在线免费观看| 亚洲日韩三级| 精品国产一区二区三区久久久蜜月| 17.3c一起起草| 免费看a的网站| 欧美日韩一区二区在线| 久久XXX| 特级特黄AAAAAAAA片| 999高清无码| 日日夜夜综合| 思思在线视频| 成人一级视频| 激情五月毛片| 国产无码电影在线观看| 国产亚洲欧美精品综合在线| 高h视频在线观看| 91大神在线资源观看无广告| 三区在线观看| 黄网免费| 日本黄色免费| 91丨九色丨蝌蚪丨肥女| 一本一道久久综合| 豆花视频成人版www满18| 蜜桃视频网站| 天天爽天天爽夜夜爽| 鸡巴操骚逼视频| 北条麻妃无码中文| 免费一级片| 高清无码网站在线观看| 国产中文在线视频| 亚洲九九九九| 中文字幕日日| 天天看天天爽| 91成人精品一区二区| 国产精品久久久久久久久久久久| 婷色五月| 欧美精品亚洲| 嫩草国产| 北条麻妃无码精品AV怎么看| 加勒比一区二区三区| 色天使亚洲| 超碰人人操| 五月丁香婷婷在线观看| 日本A片免费观看| 免费a级毛片| 国产一视频| 亚洲无码图| 国产成人av在线播放| av人人| 亚洲AV无码久久寂寞少妇多毛| 色片在线观看| 姐弟乱伦性爱| 少妇久久久久久久久久| 久久免费视频播放| h片在线播放| 免费一级A| 日韩AⅤ| 东京热综合| 9l人人澡人人妻人人精品| AV网站在线免费观看| 五月激情综合网| 国产1024在线| 国产男女视频| 亚洲狠狠操| 男女视频网站在线观看| 欧美黑人大吊| 婷婷激情四射| 毛片性爱视屏| 久久另类TS人妖一区二区| 操中国老女人| 日韩视频免费在线| 韩国无码一区| 中文字幕色| 久久五月天综合| 亚洲精品999| 亚洲三级视频| 人人干超碰| www.91在线| www.天天射视频| 亚欧一区二区| 国产区av| 欧美性爱高清| 国产精品成人免费视频| 国产成人aV| 高清免费在线中文Av| 日韩操逼逼| 91精品国产成人观看| 大鸡吧操视频| 成人中文字幕在线| 国产色秘乱码一区二区三区| 午夜91| 豆花成人视频| 日韩在线小电影| 欧美激情无码一区二区三区张丽 | 俺也去色色| 午夜福利1000| 黄色日逼视频| 粉嫩99精品99久久久久久特污 |