精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Netty入門實(shí)踐:模擬IM聊天

開發(fā) 網(wǎng)絡(luò)
本文以入門實(shí)踐為主,通過原理+代碼的方式,實(shí)現(xiàn)一個(gè)簡易IM聊天功能。

我們使用的框架幾乎都有網(wǎng)絡(luò)通信的模塊,比如常見的Dubbo、RocketMQ、ElasticSearch等。它們的網(wǎng)絡(luò)通信模塊使用Netty實(shí)現(xiàn),之所以選擇Netty,有兩個(gè)主要原因:

  • Netty封裝了復(fù)雜的JDK 的 NIO操作,還封裝了各種復(fù)雜的異常場景,豐富的API使得在使用上也非常方便,幾行代碼就可以實(shí)現(xiàn)高性能的網(wǎng)絡(luò)通信功能。
  • Netty已經(jīng)經(jīng)歷各種大型中間件的生產(chǎn)環(huán)境的驗(yàn)證,高可用性和健壯性都得到了全方位驗(yàn)證,用起來更放心。

本文以入門實(shí)踐為主,通過原理+代碼的方式,實(shí)現(xiàn)一個(gè)簡易IM聊天功能。分為兩個(gè)部分:Netty的核心概念、IM聊天簡易實(shí)現(xiàn)。

一、Netty核心概念

1、通信流程

既然是網(wǎng)絡(luò)通信,那肯定有服務(wù)端和客戶端。在客戶端-A和客戶端-B通信的過程中,實(shí)際上是利用服務(wù)端作為消息中轉(zhuǎn)站,來實(shí)現(xiàn)A-B通信的。

不管是點(diǎn)-點(diǎn)通信,還是群通信,都可以認(rèn)為是客戶端-服務(wù)端之間的通信,有了這一點(diǎn),許多設(shè)計(jì)方案都可以輕松理解。

2、服務(wù)端核心概念

(1) Boss線程:Boss線程負(fù)責(zé)監(jiān)聽端口,接受新的連接,監(jiān)聽連接的數(shù)據(jù)讀寫變化。

(2) Worker線程:Worker線程負(fù)責(zé)處理具體的業(yè)務(wù)邏輯,Boss線程接收到連接的讀寫變化后,然后交給Worker處理具體業(yè)務(wù)邏輯。

(3) 服務(wù)端的IO模型:Netty支持使用NIO和BIO進(jìn)行通信,可以自行設(shè)置。一般使用NioServerSocketChannel來指定NIO模型。

(4) 服務(wù)端引導(dǎo)類:服務(wù)端通過引導(dǎo)類 ServerBootstrap來啟動(dòng)一系列的工作。

3、客戶端核心概念

(1) Worker線程:客戶端只有工作線程的概念,負(fù)責(zé)連接到服務(wù)端,監(jiān)聽數(shù)據(jù)讀寫變化。

(2) 客戶端的IO模型:一般使用NioSocketChannel指定客戶端的NIO模型

(3) 客戶端引導(dǎo)類:客戶端通過引導(dǎo)類Bootstrap來啟動(dòng)一些列工作。

4、通用核心概念

(1) Handler:負(fù)責(zé)處理接受到的消息,大部分的業(yè)務(wù)邏輯都是放在Handler里處理。自定義的Handler一般繼承于SimpleChannelInboundHandler或者ChannelInboundHandlerAdapter。

(2) ByteBuf和編碼、解碼:數(shù)據(jù)的載體,Java對象編碼成字節(jié)碼,存放于ByteBuf,然后發(fā)送出去。服務(wù)端接收到消息后,從ByteBuf中取出數(shù)據(jù),解碼成Java對象。

(3) 通訊協(xié)議:許多框架都會(huì)自定義一套自己的協(xié)議,這樣比較符合業(yè)務(wù)。比如dubbo協(xié)議、hessian協(xié)議。

一般的協(xié)議包括如下部分:魔數(shù)、版本號、序列化算法、指令、數(shù)據(jù)長度、數(shù)據(jù)內(nèi)容,其余的都是為了適配自身業(yè)務(wù)而定的。

  • 魔數(shù):一般是固定數(shù)字,用來快速判斷是否符合本協(xié)議,如果不符合本協(xié)議,則快速失敗。
  • 版本號:一般無需改動(dòng),如果早期設(shè)置的協(xié)議到了后續(xù)不適用了,在升級版本號。
  • 序列化算法:Java對象轉(zhuǎn)序列化的方式,比如JSON。
  • 指令:操作大類。比如說登錄指令、單點(diǎn)發(fā)送消息指令、建群指令等。這樣服務(wù)端接收到對應(yīng)指令就用對應(yīng)的Handler去處理業(yè)務(wù)邏輯。指令占用的字節(jié)數(shù)可以根據(jù)自身業(yè)務(wù)適當(dāng)調(diào)大。
  • 數(shù)據(jù)長度:用來記錄本次數(shù)據(jù)的長度。
  • 數(shù)據(jù)內(nèi)容:具體消息內(nèi)容,比如聊天時(shí)的消息、登錄時(shí)的用戶名密碼等。

(4) 粘包拆包

Netty屬于上層應(yīng)用,在發(fā)送消息時(shí),還是通過底層操作系統(tǒng)將數(shù)據(jù)發(fā)送出去,操作系統(tǒng)在發(fā)送數(shù)據(jù)時(shí),不會(huì)按照我們設(shè)想的消息長度去發(fā)送內(nèi)容。這就需要我們在接收到內(nèi)容時(shí),自行做好內(nèi)容的分割和等待。

比如有一條消息1024字節(jié),如果接受的內(nèi)容沒這么長就需要繼續(xù)等待,等這條消息的內(nèi)容完整后,在處理。如果接受的內(nèi)容包含了1條完整消息和1條不完整的消息,那么就需要拆分內(nèi)容,將完整的消息先傳遞到后面處理,剩下不完整的消息則繼續(xù)等待下一個(gè)內(nèi)容。

Netty自帶了幾種拆包器:固定長度的拆包器 FixedLengthFrameDecoder、行拆包器 LineBasedFrameDecoder、分隔符拆包器 DelimiterBasedFrameDecoder、長度域拆包器LengthFieldBasedFrameDecoder。

一般在使用自定義協(xié)議時(shí),會(huì)使用:長度域拆包器 LengthFieldBasedFrameDecoder。

(5) 空閑檢測和定時(shí)心跳

在服務(wù)端和客戶端的通信過程中,有時(shí)候會(huì)出現(xiàn)假死連接,或者長時(shí)間沒有消息傳遞需要釋放連接。對于這些連接,我們需要及時(shí)釋放,畢竟每條連接都占用著CPU和內(nèi)存資源。大量這種連接如果不及時(shí)釋放,服務(wù)器資源遲早會(huì)耗盡,最終崩潰。

應(yīng)對這種問題的解決方式是:Netty提供了IdleStateHandler做空閑檢測,用來檢測連接是否活躍,如果再指定的時(shí)間內(nèi),沒有活躍,那么就關(guān)閉連接。然后就是客戶端定時(shí)發(fā)送心跳請求,服務(wù)器響應(yīng)心跳請求。

二、IM聊天簡易實(shí)現(xiàn)

介紹完Netty的核心概念,接下來以一個(gè)簡易的點(diǎn)對點(diǎn)IM聊天,將核心概念融入到案例中。IM聊天的核心模塊大致是如下幾個(gè):

1、通信主體流程

通信主體流程就是搭建好:服務(wù)端、客戶端、兩端正常建立連接進(jìn)行通信。

服務(wù)端代碼:

public static void main(String[] args) {
    ServerBootstrap serverBootstrap = new ServerBootstrap();

    NioEventLoopGroup boss = new NioEventLoopGroup();
    NioEventLoopGroup worker = new NioEventLoopGroup();
    serverBootstrap
            .group(boss, worker)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<NioSocketChannel>() {
                protected void initChannel(NioSocketChannel ch) {
                    ch.pipeline().addLast(new StringDecoder());
                    ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                            System.out.println("server accept: " + msg);
                        }
                    });
                }
            });
    serverBootstrap.bind(9000)
            .addListener(future -> {
                if (future.isSuccess()) {
                    System.out.println("端口9000綁定成功");
                } else {
                    System.err.println("端口9000綁定失敗");
                }
            });
}

客戶端代碼:

public static void main(String[] args) throws InterruptedException {
    Bootstrap bootstrap = new Bootstrap();
    NioEventLoopGroup group = new NioEventLoopGroup();

    bootstrap.group(group)
            .channel(NioSocketChannel.class)
            .handler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) {
                    ch.pipeline().addLast(new StringEncoder());
                }
            });

    bootstrap.connect("127.0.0.1", 9000)
            .addListener(future -> {
                if (future.isSuccess()) {
                    System.out.println("鏈接服務(wù)端成功");
                    Channel channel = ((ChannelFuture) future).channel();
                    channel.writeAndFlush("我是客戶端A");
                } else {
                    System.err.println("連接服務(wù)端失敗");
                }
            });
}

2、數(shù)據(jù)包—包含通訊協(xié)議

定義數(shù)據(jù)包的抽象類,后續(xù)的各種類型的數(shù)據(jù)包都繼承此類。數(shù)據(jù)包中定義通訊協(xié)議的各種字段。

@Data
public abstract class Packet {
    /**
     * 協(xié)議版本
     */
    private Byte version = 1;

    /**
     * 指令,此處有多種實(shí)現(xiàn):比如登錄、登出、單聊、建群等等
     *
     * @return
     */
    public abstract Byte getCommand();

    /**
     * 獲取算法,默認(rèn)使用JSON,如果使用其余算法,子類重寫此方法
     *
     * @return
     */
    public Byte getSerializeAlgorithm() {
        return SerializerAlgorithm.JSON;
    }
}

public class LoginRequestPacket extends Packet {
    private String userName;

    private String password;

    @Override
    public Byte getCommand() {
        return Command.LOGIN_REQUEST;
    }
}

3、序列化器

定義序列化器,功能包括:序列化、反序列化。可以定義多種序列化算法,文中以JSON為例。

public interface Serializer {
    /**
     * 序列化算法
     *
     * @return
     */
    byte getSerializerAlgorithm();

    /**
     * java 對象轉(zhuǎn)換成二進(jìn)制
     */
    byte[] serialize(Object object);

    /**
     * 二進(jìn)制轉(zhuǎn)換成 java 對象
     */
    <T> T deserialize(Class<T> clazz, byte[] bytes);
}

public class JSONSerializer implements Serializer {

    @Override
    public byte getSerializerAlgorithm() {
        return SerializerAlgorithm.JSON;
    }

    @Override
    public byte[] serialize(Object object) {
        return JSON.toJSONBytes(object);
    }

    @Override
    public <T> T deserialize(Class<T> clazz, byte[] bytes) {
        return JSON.parseObject(bytes, clazz);
    }
}

4、編解碼器

有了通訊協(xié)議、有了序列化協(xié)議,接下來就是對數(shù)據(jù)的編碼和解碼了。

public void encode(ByteBuf byteBuf, Packet packet) {
    Serializer serializer = getSerializer(packet.getSerializeAlgorithm());

    // 1. 序列化 java 對象
    byte[] bytes = serializer.serialize(packet);

    // 2. 實(shí)際編碼過程
    byteBuf.writeInt(MAGIC_NUMBER);
    byteBuf.writeByte(packet.getVersion());
    byteBuf.writeByte(packet.getSerializeAlgorithm());
    byteBuf.writeByte(packet.getCommand());
    byteBuf.writeInt(bytes.length);
    byteBuf.writeBytes(bytes);
}


public Packet decode(ByteBuf byteBuf) {
    // 跳過 magic number
    byteBuf.skipBytes(4);
    // 跳過版本號
    byteBuf.skipBytes(1);
    // 讀取序列化算法
    byte serializeAlgorithm = byteBuf.readByte();
    // 讀取指令
    byte command = byteBuf.readByte();
    // 讀取數(shù)據(jù)包長度
    int length = byteBuf.readInt();
    // 讀取數(shù)據(jù)
    byte[] bytes = new byte[length];
    byteBuf.readBytes(bytes);

    Class<? extends Packet> requestType = getRequestType(command);
    Serializer serializer = getSerializer(serializeAlgorithm);

    if (requestType != null && serializer != null) {
        return serializer.deserialize(requestType, bytes);
    }

    return null;
}

5、消息處理器Handler

以上把通訊的基本架子和收發(fā)消息的數(shù)據(jù)包、協(xié)議、編解碼器等基礎(chǔ)工具已經(jīng)做完,接下來就是編寫Handler實(shí)現(xiàn)具體的業(yè)務(wù)邏輯了。

這里以客戶端發(fā)起登錄功能為例,分3步,消息收發(fā)也是類似:

  • 先在客戶端發(fā)送登錄請求數(shù)據(jù)包。
  • 服務(wù)端接收到登錄請求數(shù)據(jù)包后,在服務(wù)端的Handler里做業(yè)務(wù)邏輯處理,然后發(fā)送響應(yīng)給客戶端。
  • 客戶端接收到登錄響應(yīng)數(shù)據(jù)包后,在客戶端的Handler里做業(yè)務(wù)邏輯處理。

效果如下:

核心代碼如下:

  • 客戶端發(fā)送請求
bootstrap.connect("127.0.0.1", 9000)
                .addListener(future -> {
                    if (future.isSuccess()) {
                        System.out.println("連接服務(wù)端成功");
                        Channel channel = ((ChannelFuture) future).channel();
                        // 連接之后,假設(shè)再這里發(fā)起各種操作指令,采用異步線程開始發(fā)送各種指令,發(fā)送數(shù)據(jù)用到的的channel是必不可少的
                        sendActionCommand(channel);
                    } else {
                        System.err.println("連接服務(wù)端失敗");
                    }
                });

private static void sendActionCommand(Channel channel) {
        // 直接采用控制臺(tái)輸入的方式,模擬操作指令
        Scanner scanner = new Scanner(System.in);
        LoginActionCommand loginActionCommand = new LoginActionCommand();
        new Thread(() -> {
            loginActionCommand.exec(scanner, channel);
        }).start();
    }
  • 服務(wù)端接受請求,并且處理
protected void channelRead0(ChannelHandlerContext ctx, LoginRequestPacket loginRequestPacket) {
    LoginResponsePacket loginResponsePacket = new LoginResponsePacket();
    loginResponsePacket.setVersion(loginRequestPacket.getVersion());
    loginResponsePacket.setUserName(loginRequestPacket.getUserName());

    if (valid(loginRequestPacket)) {
        loginResponsePacket.setSuccess(true);
        String userId = IDUtil.randomId();
        loginResponsePacket.setUserId(userId);
        System.out.println("[" + loginRequestPacket.getUserName() + "]登錄成功");
        SessionUtil.bindSession(new Session(userId, loginRequestPacket.getUserName()), ctx.channel());
    } else {
        loginResponsePacket.setReason("校驗(yàn)失敗");
        loginResponsePacket.setSuccess(false);
        System.out.println("登錄失敗!");
    }

    // 登錄響應(yīng)
    ctx.writeAndFlush(loginResponsePacket);
}

private boolean valid(LoginRequestPacket loginRequestPacket) {
    System.out.println("服務(wù)端LoginRequestHandler,正在校驗(yàn)客戶端登錄請求");
    return true;
}
  • 客戶端接受響應(yīng),并且處理
public class LoginResponseHandler extends SimpleChannelInboundHandler<LoginResponsePacket> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, LoginResponsePacket loginResponsePacket) {
        String userId = loginResponsePacket.getUserId();
        String userName = loginResponsePacket.getUserName();

        if (loginResponsePacket.isSuccess()) {
            System.out.println("[" + userName + "]登錄成功,userId為: " + loginResponsePacket.getUserId());
            SessionUtil.bindSession(new Session(userId, userName), ctx.channel());
        } else {
            System.out.println("[" + userName + "]登錄失敗,原因?yàn)椋? + loginResponsePacket.getReason());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println("客戶端連接被關(guān)閉!");
    }
}

6、空閑檢測和定時(shí)心跳

主流程和主要功能已經(jīng)實(shí)現(xiàn),還剩最后一個(gè)空閑檢測和定時(shí)心跳。

實(shí)現(xiàn)步驟:

  • 客戶端和服務(wù)端都先定義好空閑檢測。如果再規(guī)定的時(shí)間內(nèi)沒有數(shù)據(jù)傳輸,則關(guān)閉通道。
  • 客戶端定時(shí)發(fā)送心跳
  • 服務(wù)端處理心跳請求,發(fā)送響應(yīng)給客戶端

核心代碼:

  • 空閑檢測代碼:
/**
 * IM聊天空閑檢測器
 * 比如:20秒內(nèi)沒有數(shù)據(jù),則關(guān)閉通道
 */
public class ImIdleStateHandler extends IdleStateHandler {

    private static final int READER_IDLE_TIME = 20;

    public ImIdleStateHandler() {
        super(READER_IDLE_TIME, 0, 0, TimeUnit.SECONDS);
    }

    @Override
    protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) {
        System.out.println(READER_IDLE_TIME + "秒內(nèi)未讀到數(shù)據(jù),關(guān)閉連接!");
        ctx.channel().close();
    }
}
  • 客戶端定時(shí)心跳代碼:
public void channelActive(ChannelHandlerContext ctx) throws Exception {
        scheduleSendHeartBeat(ctx);

        super.channelActive(ctx);
    }

    private void scheduleSendHeartBeat(ChannelHandlerContext ctx) {
        // 此處無需使用scheduleAtFixedRate,因?yàn)槿绻ǖ朗Ш螅蜔o需在發(fā)起心跳了,按照目前的方式是最好的:成功一次安排一次
        ctx.executor().schedule(() -> {

            if (ctx.channel().isActive()) {
                System.out.println("定時(shí)任務(wù)發(fā)送心跳!");
                ctx.writeAndFlush(new HeartBeatRequestPacket());
                scheduleSendHeartBeat(ctx);
            }

        }, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
    }
  • 服務(wù)端響應(yīng)心跳代碼:
public class ImIdleStateHandler extends IdleStateHandler {

    private static final int READER_IDLE_TIME = 20;

    public ImIdleStateHandler() {
        super(READER_IDLE_TIME, 0, 0, TimeUnit.SECONDS);
    }

    @Override
    protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) {
        System.out.println(READER_IDLE_TIME + "秒內(nèi)未讀到數(shù)據(jù),關(guān)閉連接!");
        ctx.channel().close();
    }
}

三、總結(jié)

本文介紹了Netty的核心概念,以及基本使用方法,希望能夠幫到你。本文核心詞:

  • 通信流程
  • Boss線程、Worker線程
  • 處理消息的Handler
  • 通訊協(xié)議、序列化協(xié)議、編解碼器
  • 空閑檢測、定時(shí)心跳

本文完整代碼:https://github.com/yclxiao/netty-demo.git

責(zé)任編輯:趙寧寧 來源: 不焦躁的程序員
相關(guān)推薦

2012-08-13 13:03:31

Web

2023-03-27 18:33:47

客服IM消息

2019-12-10 09:20:30

NettyBIO開發(fā)

2023-02-10 08:16:48

WebSocket簡易聊天室

2021-08-09 09:48:16

NettyChannelHand架構(gòu)

2024-10-14 08:09:08

2020-12-14 15:59:10

PythonWechaty機(jī)器人

2024-10-24 20:48:04

Netty線程Java

2018-04-20 09:36:23

NettyWebSocket京東

2016-08-05 13:19:29

GET請求github項(xiàng)目 POST請求

2023-11-28 08:49:01

短輪詢WebSocket長輪詢

2020-09-30 18:00:48

JavaSpring BootIM

2020-04-15 08:33:43

Netty網(wǎng)絡(luò)通信

2022-07-28 07:00:56

Nuclei漏洞掃描器

2009-09-04 16:05:08

2020-12-04 10:42:54

GithubSSDNode.js

2010-12-08 09:03:40

SQLiteAndroid

2023-09-11 10:53:32

2019-04-24 23:49:57

宜人貸蜂巢API網(wǎng)關(guān)Netty

2022-09-26 08:25:56

監(jiān)控平臺(tái)微服務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

91蜜桃臀久久一区二区| 精品国产一区二区三区不卡| 欧美一区二区视频在线| 亚洲一级片免费看| 午夜日韩视频| 亚洲男人天堂2019| 三级一区二区三区| 92久久精品| 国产日韩亚洲欧美综合| 成人午夜两性视频| 国产一区二区99| 久久理论电影| 日韩av在线免播放器| www.99r| 9999精品成人免费毛片在线看| 国产欧美一区二区在线| 不卡一区二区三区四区五区| 黄色污污视频软件| 欧美黄色一区二区| 国产性色av一区二区| 久久久久久无码精品人妻一区二区| 欧美久久天堂| 一区二区三区在线看| 欧美一区观看| 日本精品一二区| 美腿丝袜在线亚洲一区 | 久久久水蜜桃| 亚洲av无码一区二区三区dv| 美女视频黄 久久| 38少妇精品导航| 538精品在线观看| 日韩免费久久| 亚洲欧美日韩第一区| 中文字幕人妻一区| 国产福利一区二区三区在线播放| 午夜精品视频一区| 成人在线免费观看网址| 永久av在线| 91啪九色porn原创视频在线观看| 91视频网页| 国产精品久久久久久久一区二区| 日本va欧美va瓶| 欧美孕妇性xx| 国产99久久久| 免费在线亚洲| 日本国产精品视频| 草久视频在线观看| 国产亚洲综合精品| 97久久久久久| 精品99在线观看| 欧美成人日韩| 欧美第一黄色网| 麻豆疯狂做受xxxx高潮视频| 亚洲二区三区不卡| 久久精品电影网站| 亚洲人做受高潮| 亚欧美无遮挡hd高清在线视频| 在线观看日韩专区| 99久久99久久精品免费| 色135综合网| 日韩在线观看免费全| 国产一区在线观看免费| 五月婷婷亚洲| 大胆欧美人体视频| 看片网站在线观看| 狠狠综合久久| 69av在线视频| 青青草视频在线观看免费| 日韩精品一二三区| 国产欧美一区二区三区久久 | 日本色护士高潮视频在线观看| 亚洲色大成网站www久久九九| 在线观看18视频网站| 一色桃子av在线| 亚洲va韩国va欧美va精品| 一女被多男玩喷潮视频| 亚洲四虎影院| 制服丝袜亚洲色图| 性农村xxxxx小树林| 精品麻豆剧传媒av国产九九九| 91精品欧美久久久久久动漫| 亚洲一级片av| 欧美人与动xxxxz0oz| 亚洲欧洲国产一区| 青花影视在线观看免费高清| 亚洲国产精品一区制服丝袜| 国产成人精品一区二区| 国产精品免费无遮挡| 成人免费视频免费观看| 欧美成人在线免费观看| 黄色在线免费网站| 香蕉成人啪国产精品视频综合网| 国产成人精品无码播放| 国产精一区二区| 亚洲精品福利视频| 无码人妻精品中文字幕| 亚洲精品黄色| 国产日韩精品在线观看| 内射后入在线观看一区| 欧美激情中文字幕一区二区| 久久久久99精品成人片| 日韩欧美少妇| 欧美刺激脚交jootjob| 国产肥白大熟妇bbbb视频| 五月天综合网站| 欧洲中文字幕国产精品| 99精品免费观看| 久久人人97超碰com| 国产精品免费看久久久无码| 欧美片第1页| 欧美成人精品1314www| 嘿嘿视频在线观看| 国产欧美高清| 成人av网站观看| 日本中文字幕电影在线免费观看| 午夜成人免费视频| 91精品国产三级| 精品国产一区探花在线观看| 亚州国产精品久久久| 国产婷婷在线视频| 国产精品视频免费看| 国产h视频在线播放| 国产精品国产三级在线观看| 国产一区二区三区在线看| 欧美三级黄色大片| 久久一区亚洲| 国产精品一级久久久| 欧美性天天影视| 在线观看视频欧美| 日本丰满少妇裸体自慰 | 欧洲av无码放荡人妇网站| 亚洲不卡在线| 久热精品视频在线免费观看| 中文字幕精品一区二| 久久久精品免费观看| 玩弄中年熟妇正在播放| 国产精品tv| 久久久久久网址| 亚洲精品喷潮一区二区三区| 亚洲人成精品久久久久久| 欧美成年人视频在线观看| 九一成人免费视频| 欧美亚洲国产视频| 三级理论午夜在线观看| 精品国产成人在线| 国产精品久久AV无码| 亚洲国产裸拍裸体视频在线观看乱了中文 | 91色porny在线视频| www污在线观看| 国产乱人伦丫前精品视频| 欧美乱妇40p| 亚洲av无码乱码国产精品久久| 亚洲人成网站影音先锋播放| 亚洲制服在线观看| 雨宫琴音一区二区三区| 91色p视频在线| а天堂中文在线官网| 日韩一区二区三区电影| 九九热精品免费视频| 粉嫩av一区二区三区在线播放 | 蜜桃视频成人| 日韩电影av| 伊人伊成久久人综合网小说 | 欧美成人乱码一区二区三区| 久久精品国产亚洲av香蕉| 成人精品国产一区二区4080| 91免费黄视频| 午夜精品福利影院| 国产成人精品综合久久久| wwwxxx在线观看| 538在线一区二区精品国产| 91九色丨porny丨极品女神| 国产成人鲁色资源国产91色综| 久久av综合网| 国产免费久久| 成人免费视频网址| 女同视频在线观看| 亚洲精品视频网上网址在线观看| 一级一片免费看| 中文字幕一区二区三区在线不卡| xxxx国产视频| 久久精品综合| 手机看片日韩国产| 久久综合社区| 国产日韩精品电影| √天堂8资源中文在线| 国产午夜精品全部视频在线播放| 国产又粗又猛又爽又黄的视频一 | 国产天堂第一区| 亚洲黄色小说网站| 自拍偷拍中文字幕| 国产精品综合久久| 欧美日韩在线视频一区二区三区| 日韩欧美在线中字| 国产精品一区二区三区免费| jizz亚洲女人高潮大叫| 欧美精品成人在线| 成人欧美亚洲| 亚洲成人教育av| 在线观看亚洲国产| 午夜av一区二区三区| 国内毛片毛片毛片毛片毛片| 播五月开心婷婷综合| 一级在线免费视频| 日本网站在线免费观看视频| 欧洲激情综合| 91啪国产在线| 日本精品不卡| 久久久久国产精品免费网站| 69av亚洲| 亚洲欧洲黄色网| 少妇人妻精品一区二区三区| 欧美日韩视频在线一区二区| 国产成人在线视频观看| 亚洲伦理在线精品| 欧美人妻一区二区三区 | 中文字幕一区二区三区人妻电影| 国产精品一区二区果冻传媒| 天天爱天天操天天干| 亚洲美女91| 国产经典久久久| 日韩欧美精品综合| 热re99久久精品国99热蜜月 | 亚洲精品在线免费| 天海翼精品一区二区三区| 亚洲精品免费在线视频| 成人在线黄色| 国产91热爆ts人妖在线| 成人国产电影在线观看| 欧美黑人巨大精品一区二区| 麻豆免费在线观看| 中文字幕日韩欧美在线视频| 男女视频在线观看免费| 日韩av影视综合网| 日韩有码第一页| 日韩视频一区二区三区| 国产精品久久久久久久久久久久久久久久久久 | 亚洲成人日韩| 一区精品视频| 日本不卡二三区| 日韩精品伦理第一区| 亚洲第一论坛sis| 久久草视频在线看| 日韩最新在线| 精品一区二区三区国产| 国内精品免费| 精品国产乱码久久久久久丨区2区| 97久久综合精品久久久综合| 国产精品久久久久久久天堂第1集 国产精品久久久久久久免费大片 国产精品久久久久久久久婷婷 | 亚洲免费久久| 欧美理论电影大全| 视频一区视频二区视频三区高| 精品国产一区二区三区久久久樱花 | 俄罗斯精品一区二区三区| 日韩精品免费视频一区二区三区 | 偷拍视屏一区| 欧美激情第六页| 国内精品久久久久久久久电影网| 日本一区免费观看| 精品精品久久| 伊甸园精品99久久久久久| 天天色综合色| 欧美一级中文字幕| 亚洲狠狠婷婷| 久久久久免费精品| 亚洲综合不卡| 国产精品人人爽人人爽| 精品一区二区成人精品| 中国特级黄色片| av电影在线观看一区| 精品国产无码在线观看| 国产精品久久久久久久久动漫| av成人免费网站| 亚洲成人www| 中文字幕在线欧美| 欧美日韩性生活| 草逼视频免费看| 日韩高清a**址| 亚洲s色大片| 欧美激情手机在线视频 | 在线看一区二区| 国产乱码精品一区二区| 亚洲第一av网站| 二人午夜免费观看在线视频| 久久久精品网站| 密臀av在线播放| 成人午夜两性视频| 台湾佬综合网| 日韩免费观看高清| 五月天免费网站| 亚洲精品福利视频网站| 久久黄色精品视频| 欧美高清视频一二三区| 手机av免费在线观看| 色老头一区二区三区在线观看| 国产精品偷拍| 国产精品一区二区3区| 成人搞黄视频| 亚洲午夜精品一区二区| 一本一本久久| 91在线第一页| 国产亚洲1区2区3区| 久艹视频在线观看| 精品视频一区 二区 三区| 欧美一区二区三区成人片在线| 中文字幕日韩精品在线| 成人bbav| 国产高清精品一区二区三区| 日韩国产欧美| 99热成人精品热久久66| 国产精品911| 99精品中文字幕| 色婷婷av一区二区三区软件| 亚洲av无码一区二区三区性色 | 国产在线一区二区三区播放| 欧美高清在线| 成人久久久久久久久| 丁香一区二区三区| 免费成年人视频在线观看| 色老汉av一区二区三区| 天堂在线资源8| 欧美日韩成人网| 日韩国产一二三区| 日韩av一区二区三区美女毛片| 一本久道久久久| 91精产国品一二三| 中文字幕一区二区三| 亚洲 小说区 图片区| 日韩精品在线观| 国产福利片在线观看| 成人av男人的天堂| 欧美精品激情| 国产xxxxhd| 亚洲视频在线观看一区| 国产精品高潮呻吟久久久| 中文字幕自拍vr一区二区三区| 欧美7777| 欧美一区二视频在线免费观看| 亚洲神马久久| 一本色道综合久久欧美日韩精品| 亚洲一区二区三区四区五区中文| 国产女人高潮时对白| 久久亚洲影音av资源网| 在线不卡一区| 亚洲成人动漫在线| 精品一区二区免费| 肉色超薄丝袜脚交69xx图片| 欧美在线免费播放| 懂色av中文在线| 国产精品九九久久久久久久| 欧洲grand老妇人| 中文字幕国内自拍| 国产精品国产精品国产专区不蜜 | 国产精品资源在线看| 1024手机在线视频| 3d动漫精品啪啪1区2区免费| av片在线观看| 国产经典一区二区三区| 亚洲精品黄色| 一级黄色性视频| 欧美日韩二区三区| 69成人在线| 精选一区二区三区四区五区| 午夜在线观看免费一区| 国精品无码人妻一区二区三区| 手机在线免费看av| 国产成人高清激情视频在线观看| 国产一区二区区别| 日本美女视频一区| 一区二区三区在线免费播放| 五月婷婷在线播放| 国产99久久久欧美黑人| 99精品国产一区二区三区| 熟妇无码乱子成人精品| 亚洲国产精品麻豆| 久久经典视频| 91亚洲精品一区二区| 亚洲第一精品影视| 午夜精产品一区二区在线观看的| 欧美男生操女生| 51精品在线| 神马影院我不卡| 国产 日韩 欧美大片| 中文字幕高清在线免费播放| 久久精品人人做人人爽| 久久久久久毛片免费看| 中文字幕天天干| 亚洲午夜久久久久久久久电影院 | 北条麻妃在线一区二区| 成人影院中文字幕| 不要播放器的av网站| 亚洲欧美日韩一区| 亚洲色图另类小说| 91香蕉亚洲精品| 久久久青草婷婷精品综合日韩| 亚洲人与黑人屁股眼交| 亚洲精品资源在线| 亚洲专区**| 欧美第一页浮力影院| 亚洲成年人网站在线观看|