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

通過面向對象設計串口協議

原創 精選
開發
要想通過串口傳遞具有特定意義的數據時,通常需要對二進制數據加以區分、組合、編碼,以賦予其表達復雜數據結構的能力 —— 串口通信協議。

作者 | 廖桉冬

背景

自Java語言流行以來,其主打的面向對象編程也成為了家喻戶曉的一種程序設計思想:“封裝、繼承、多態”、“易維護、易復用、易擴展”,“解耦、隔離”。

而以過程為中心的“面向過程編程”,通常會優先分析出解決問題所需的步驟,然后用函數依次實現這些步驟,最后串聯起來依次調用即可,是一種基于順序的思維方式。

常見的支持面向過程的編程語言有 C語言、COBOL 語言等,被廣泛地應用在系統內核、IoT、物聯網等領域。其中一個比較典型的案例是串口通信協議的集成開發(驅動、SDK),雖然大多數的Web應用都已經跨入了“Json Free”的時代,但大量的嵌入式設備使用仍是串口協議,以獲得能耗、體積和效率等方面的優勢。而現有的驅動大多由C,使用面向過程的方式編寫的。

舉個栗子 ,當我們的應用需要提供線下的服務:用戶在門戶店可以使用一體機訪問我們的服務,可以選擇使用線下POS機進行刷卡支付(類比肯德基)。我們不僅要在網頁后臺計算出訂單價格,還要通知POS機開始“接單”,完成刷卡操作并及時返回交易數據。

然而,當打開POS機“附贈”的接口文檔時,晃眼的二進制案例、復雜的數據結構卻讓我們手足無措 —— 所有的數據都需要通過那根RS232串口線,以“01010101”的數據與相連的一體機進行交互。

PS:一體機是一臺Windows物理機,通過COM接口(RS232、9針線)連接POS機設備;文章中內含代碼示例,電腦端觀看效果更佳。

令人頭暈的二進制

不同于我們日常所使用的HTTP協議:

  • 具有標準的報文結構和數據編碼
  • 完備的SDK和生態鏈工具,可以很容易實現CS(Client-Server)架構的數據傳輸
  • 無需關注應用層(ISO Application Layer)以下的技術細節

而串口更貼近于ISO的物理層:通過指定頻率(Baud 波特率)的高低電平(0/1)來傳輸數據。

因此要想通過串口傳遞具有特定意義的數據時,通常需要對二進制數據加以區分、組合、編碼,以賦予其表達復雜數據結構的能力 —— 串口通信協議。例如一個典型(但又稍顯復雜)的串口協議報文:

一個串口消息的數據結構(使用16進制表示字節流示例)

串=“串行”,數據在傳輸過程中都是按順序寫入、讀出的,因此需要準確的告訴服務方:

  • StartToken / EndToken,標記當前消息何時開始何時結束
  • Length,當前欲讀取的數據長度

為了提升協議的易用性,將不同目的的數據通過類型加以區分,具有不同的序列化規則:

  • Hex(十六進制)
  • BCD(二進制化整數)
  • ASC(ASIIC碼)

數據部分則由消息頭和多組消息數據組成:

(1)關鍵字段(如ID、Code、Version)都是固定類型、固定長度的數據;

(2)而數據字段(Data)在不同的Field Code(不同場景下)是不同的:

  • 是一個變長數據,因此也需要Len在前,聲明數據長度
  • 發送、讀取時都要通過Field Code動態推斷

按照面向過程的方式按順序依次構建,創建一條消息并不是一件困難的事。然而不同的功能指令(Function Code)所包含的消息數據(Field Data)是完全不一樣的,但其發送流程、序列化方式又是一致的。如果我們面向過程,以一條功能指令為單位進行開發,不僅會出現大量重復冗余的序列化代碼,而且會丟失上層的Function、Field的業務含義, 代碼難以理解和維護。

public void decodeMsgData(byte[] msgDataBlocks, int index) throws PaymentException {
int start = 0;

for(int i = 0; i < msgDataBlocks.length; ++i) {
byte[] fieldCodeByte = new byte[]{msgDataBlocks[start], msgDataBlocks[start + 1]};
String fieldCode = new String(fieldCodeByte);
byte[] lenByte = new byte[]{msgDataBlocks[start + 2], msgDataBlocks[start + 3]};
int len = CommonUtil.convertBCDToInt(lenByte);
byte[] data = new byte[len];
System.arraycopy(msgDataBlocks, start + 4, data, 0, len);

if (!fieldCode.equals("M1") && !fieldCode.equals("HB")) {
if (fieldCode.equals("J4")) {
handleJ4(data);
}
} else if (fieldCode.equals("X5")) {
handleX5(data);
} else if ...
}
}

解析某一種指令的序列化代碼,充斥著難以理解的變量和混亂的處理邏輯

二進制數據的轉換、枚舉值的配置、業務邏輯的處理耦合在同一個類,甚至同一個方法中,想要梳理出代碼的執行流程都已經很困難,更不要說進一步的維護和更新了。

輪子不行就造一個。

“封裝,他使用了封裝!”

那應該如何設計既能夠適配串口數據,又能保證較高的可擴展性和可維護性呢?

  • 遇事不決,量子力學(No )
  • 遇事不決,面向對象(Yes)

面向對象的一大特點就是封裝 —— 高內聚低耦合。

首先,我將三個基本類型進行了封裝:BCD、ASC、Hex,將上層模型(Message)對二進制的依賴逐漸轉移成對基本類型BCD/ASC/Hex的依賴。同理,Start/End Token、分隔符、Length等通用數據類型也被抽取成了單獨的數據類型。

接著,祭出面向對象第二法寶 —— 多態(接口多態),定義Attribute接口來描述“如何由基本類型序列化/反序列化為二進制數據”,并由各個基本類型加以實現。

此時,上層的Message和“0101”已完全解耦,變成了含有多個"基本"字段類型的POJO類。就和我們平時所寫的Class一樣,直接使用String、Int、Double而無需擔心他們在內存的具體地址。

{
"message": {
"startToken": "Hex(08)", // Control.STX
"length": "BCD(128)", // calculate(this)
"header": {
"id": "ASC(000000000001)",
"function": "ASC(01)"
},
"data": [
{
"field": "ASC(M1)",
"length": "BCD(27)",
"value": "ASC(Hello, World)",
"separator": "Hex(1C)" // Control.SEP
}
],
"endToken": "Hex(09)", // Control.ETX
"checksum": "Hex(35)" // calculate(this)
}
}

以對象描述消息結構,以類型標明字段信息

消息對象與“基本類型”的關系

一層一層又一層

封裝之后的Message易于使用了,但開發時仍需要基于業務指令來拼裝數據,只是從對二進制的拼裝變成了對Attribute的拼裝,并不足夠表達業務含義:

(1)對于某一項指令功能(Function)的使用者來說

  • 他不關心下層數據如何被序列化、如何被發送
  • 他只關心業務數據是否正確的被設置和接收(set/get)

(2)對于某一條消息數據(Message)的傳輸者來說

  • 他不關心上層數據的業務含義
  • 他只關心二進制數據的在串口正確的傳輸

多重施法!—— 就像Attribute隔離基本類型與二進制,我們再抽象一個Field接口來隔離業務字段和消息數據。

對于指令使用者(應用開發者)來說,對某一條指令的操作更貼近命令式編程,而下層的消息組裝、序列化以及數據傳輸都被封裝到了“基本字段 Field”和“基本類型 Attribute”中。因為使用了繼承和多態,其他組件通過統一的接口類型進行協作,保證單向依賴和數據的單向流動,大大增加了可擴展性和可維護性。

@FieldDef(code = "49", length = 12)
class TransactionAmount implements Field {
Bigdecimal amount;
}
@FieldDef(code = "51", length = 25)
class AcquirerName implements Field {
String name;
}

{
"request": {
"id": "000000000001", // -> message.header.id
"function": "CREDIT_CARD", // -> message.header.function
"transactionAmount": "20.00", // message.data[]{ field:"49", value:"20.00", ... }
"acquirerName": "VISA" // message.data[]{ field:"51", value:"VISA", … }
}
}

基于消息對象再抽象一層,構建出更貼近業務的Request/Response

對指定指令 (function) 的開發和使用與底層數據結構是解耦的

  • 當我們要支持新的指令時,我們只需要實現新的Field即可 —— function 層以上
  • 當我們要更新序列化規則時,我們只需要修改協議層Attribute —— protocol 層以下

全景

SDK架構 + 數據序列化流向 + 串口異步監聽

測試

Of course,為了避免破壞已經構建好的功能,測試也是開發過程中需要慎重對待的環節(畢竟對于二進制數據來說,前面錯漏一個bit,解碼出來的消息可能完全不一樣...)

對于協議層(protocol),TDD是最佳的測試和開發方式。“A->B”,輸入輸出明確,用起來是非常舒服且高效的。但一旦涉及到串口通信部分就需要費一些心思了:

(1)串口的讀寫口是不一樣的:

  • 寫口發送數據后,需要等待并監聽讀口接收數據
  • 但Listener模式大多是多線程的,需要引入額外的同步組件來控制

(2)串口連接是長鏈接,且沒有容錯機制,可能出現丟包、斷線等情況:

  • 一般會額外設計ACK/NACK的握手機制(類似TCP)來保證通信,以觸發重試

Option 1:構造多線程測試環境

創建Stub Server:

使用了PipedInputStream、PipedOutputStream,將對串口的讀寫流包裝并導向創建的管道流中,再通過另一個線程來模擬終端POS機消費里面的數據,以實現接收請求、返回數據,驗證數據傳輸和序列化的正確性。

val serverInputStream         = PipedInputStream()
val serverOutputStream = PipedOutputStream()
val clientInputStream = PipedInputStream(serverOutputStream)
val clientOutputStream = PipedOutputStream(serverInputStream)
val serialConnection = StreamSerialChannel(clientInputStream, clientOutputStream)

val mockServer = Thread {
// 1. wait for client
Thread.sleep(50)
// 2. read request in server side
serverInputStream.read(ByteArray(requestBytes.size))
// 3. send ack to client
serverOutputStream.write(Acknowledgement.ACK.getBytes())
// 4. notify client - simulate comm listener
serialConnection.onDataAvailable()
// 5. send response to client
serverOutputStream.write(responseBytes)
// 6. notify client - simulate comm listener
serialConnection.onDataAvailable()
// 7. wait for client
Thread.sleep(50)
// 8. read ack in server side
serverInputStream.read(ByteArray(1))
}

左右互搏,模擬上下游的字節流進行數據傳輸

Option 2:使用Fake的外部程序

(1) 虛擬串口:Windows和Linux上有比較成熟的串口調試工具

我使用的是Windows Virtual Serial Port Driver,因為通過虛擬串口直接寫入(二進制)數據并不是很方便,所以我創建了兩個虛擬串口A - B分別模擬Client(發送方-一體機)和Server(接收方-POS)的串口,并連接到一起以便相互通信。與Option 1類似,啟動兩個線程分別扮演發送方、接收方并連接對應的串口,一個發一個收來模擬E2E的交互場景。

(2) USB轉串口芯片(稍微硬核)

剛好家里有一臺樹莓派,本身是自帶串口接口的,可以用來扮演POS系統。然后我從某寶購入了一塊USB轉TTL的串口芯片(因為我的電腦已經沒有九針接口了),插入到Windows主機上,使其可以通過USB向外發送串口數據。將樹莓派和TTL的Read/Write引腳反接,類似Option 2的測試方式,只是兩個線程變成了兩臺獨立主機。

CH340芯片

Option 3:使用測試機

IoT設備相對復雜,一般供應商都會提供相應的測試機器和測試環境。

但由于溝通原因,我們的測試機器很晚才拿到;因為疫情,開發人員并不能接觸到POS測試機,只能通過Zoom遠程指導式調試。因此我們需要盡早、盡快的在相對準確的環境下,驗證SDK的功能是完備的。

也因為我們提前準備的多層測試,在拿到測試機后僅花費了1小時就完成了實機集成測試。

后記(腦補)

本文主要以“面向對象”的編程思想,從新審視了串口協議的設計和實現。利用“封裝、繼承、多態”的特性,構建出更健壯、強擴展、易維護的SDK。但“面向對象”也并不是唯一解—

“抽象 —— 編程的本質,是對問題域和解決方案域的一種提煉”

筆者認為,“抽象”可能是一種更通用的編程思想。選擇合適的角度和層級分析問題,找尋共性并獲得答案,將解決問題的過程抽象為模型、方法論、原則,并推行到更多的場景和領域才是編程的核心。代碼實現僅是一個“翻譯”工作而已。

隨著抽象層級的不同,軟件從代碼、模塊的復用,上升到系統、產品的復用。就像文中的串口協議一樣,只基于下層服務給出承諾和約定,上層應用專注在當前待解決的問題領域。因此,上文雖然是闡述對串口協議的開發設計,但抽象的思維模式依然可以在不同的領域產生共鳴:

  • 高級語言 是對 匯編指令 的抽象和封裝
  • Deployment 是對 Kubernetes多個資源 的抽象和封裝
  • 云服務 是對 軟/硬件服務 的抽象和封裝
責任編輯:趙寧寧 來源: Thoughtworks洞見
相關推薦

2022-07-30 23:41:53

面向過程面向對象面向協議編程

2013-04-17 10:46:54

面向對象

2012-06-07 10:11:01

面向對象設計原則Java

2023-01-10 09:38:09

面向對象系統

2021-11-23 20:41:05

對象軟件設計

2010-06-17 16:06:18

串口協議

2013-06-07 11:31:36

面向對象設計模式

2012-12-25 10:51:39

IBMdW

2010-07-08 10:47:42

UML面向對象

2011-07-05 15:22:04

程序設計

2011-07-05 15:59:57

面向對象編程

2010-06-17 17:57:10

UML面向對象分析與設

2021-07-02 14:14:14

Python對象設計

2011-07-05 16:05:43

面向對象編程

2010-06-10 10:03:42

UML面向對象

2021-07-16 10:23:47

Python設計對象

2024-05-10 09:28:57

Python面向對象代碼

2009-09-27 14:12:12

面向對象設計單一職責

2010-06-18 11:28:14

2023-12-08 07:59:41

對象設計設計模式軟件設計
點贊
收藏

51CTO技術棧公眾號

亚洲国产日韩一区| 日本一本在线免费福利| 成人国产综合| 欧美专区18| 欧美一区二区三区免费大片 | 丝袜美腿诱惑一区二区三区| 久久99精品久久久久久动态图| 亚洲成人激情在线观看| 午夜在线视频免费观看| 日韩www视频| 欧美成人高清在线| 日本亚洲三级在线| 亚洲欧美三级在线| 免费成人在线视频网站| xxxx18国产| 亚洲精品久久| 91精品国产综合久久香蕉的特点 | 亚洲电影在线播放| 91嫩草在线视频| 五月天精品视频| 91高清在线观看视频| 日本美女视频一区二区| 欧美激情国产高清| 国产无套精品一区二区三区| 国产91在线视频蝌蚪| 狠狠色丁香婷综合久久| 亚洲乱码在线| 精品污污网站免费看| 日本成人三级电影网站| 91蜜桃视频在线观看| 精品国产导航| 婷婷六月综合亚洲| 久久人人爽爽人人爽人人片av| 激情五月色婷婷| 中文乱码免费一区二区三区下载| 亚洲色图日韩av| 成人亚洲精品777777大片| 午夜伦全在线观看| 国产一区二区三区精品视频| 欧美精品情趣视频| 成人啪啪18免费游戏链接| 成人看片在线观看| 国产精品美日韩| 国产精品一区二区3区| 精品国产视频一区二区三区| 免费一级欧美在线大片| 亚洲国产你懂的| 男女激烈动态图| 少妇高潮久久久| 日韩电影在线免费看| 精品国产一区二区三区久久| 在线观看欧美一区二区| 日韩欧美精品一区二区三区| 国产三级欧美三级日产三级99| 国产精品私拍pans大尺度在线| 国产一级淫片a视频免费观看| 日本久久精品| 日韩欧美成人一区二区| 久久久久狠狠高潮亚洲精品| 亚洲成人影院麻豆| 中文字幕乱码日本亚洲一区二区| 91网免费观看| 久久久精品毛片| 女主播福利一区| 亚洲视频在线播放| 少妇精品无码一区二区免费视频| 国产成人调教视频在线观看| 91精品国产欧美一区二区| 午夜av中文字幕| 亚洲天堂资源| 一区二区三区四区亚洲| 久久伊人资源站| 国产精品久久久久久免费免熟| 亚洲三级电影在线观看| 久久精品视频亚洲| 伊人网在线视频观看| 在线精品视频一区| 欧美日韩亚洲国产综合| 在线免费观看av网| 懂色av一区二区| 欧美精品 日韩| 手机看片福利盒子久久| аⅴ资源天堂资源库在线| 中文字幕在线观看不卡视频| 欧美日韩综合久久| 三级在线观看网站| 国产亚洲综合在线| 婷婷视频在线播放| 日韩伦理在线一区| 7777精品伊人久久久大香线蕉超级流畅| 国产成人黄色网址| 国产精品任我爽爆在线播放| 亚洲三级av在线| 欧美黑人性猛交xxx| 日韩欧美国产精品综合嫩v| 日韩精品视频中文在线观看| 无需播放器的av| 国产一区二区久久久久| 欧美精品日日鲁夜夜添| 亚洲视频在线播放免费| 久久视频精品| 亚洲最新中文字幕| 国产美女免费网站| 欧美激情第10页| 国产成人黄色av| 91视频在线视频| 久热精品在线| 国产精品av免费在线观看| 国产黄色av网站| 国产精品综合久久| 91九色露脸| 国产女主播在线写真| 久久久久久久久久久电影| 久久久神马电影| 顶级网黄在线播放| 在线观看欧美黄色| 欧美一级黄色影院| 中文字幕一区日韩精品| 中文字幕日本欧美| 欧美xxxooo| 久久精品青草| 国产成人精品午夜| 天堂中文网在线| 亚洲激情一二三区| 中国黄色片一级| 欧美高清hd| 自拍视频国产精品| av黄色在线播放| 喷水一区二区三区| 你懂的视频在线一区二区| 青草影视电视剧免费播放在线观看| 亚洲专区一二三| 分分操这里只有精品| 亚洲国产欧美日本视频| 欧美三级欧美一级| 欧美老熟妇乱大交xxxxx| 亚洲天堂久久| 777精品视频| 少妇又紧又色又爽又刺激视频| 日产国产欧美视频一区精品| 久久婷婷国产综合尤物精品| 2019中文字幕在线电影免费| 日韩欧美在线播放| 91女神在线观看| 香蕉成人app| 精品视频久久久久久久| 国产在线观看成人| 老司机精品久久| 欧美污视频久久久| 日韩不卡在线| 欧美一级久久久久久久大片| 污污污www精品国产网站| 欧美成人久久| www.成人av.com| 第九色区av在线| 欧洲一区在线电影| 在线免费看视频| 亚洲黑丝一区二区| 国产精品久久国产精品| 国产成人天天5g影院在线观看| 日韩欧美成人精品| 久久中文字幕精品| 久久成人久久爱| 小泽玛利亚av在线| 四虎成人在线| 色七七影院综合| 中文字幕精品三级久久久| 91性感美女视频| 亚洲天堂第一区| 亚洲伊人影院| 欧美一区二区色| www.久久久久久| 亚洲一区二区五区| 日本高清一区二区视频| 免费看成人吃奶视频在线| 另类专区欧美制服同性| 国产寡妇亲子伦一区二区三区四区 | 自拍偷拍亚洲一区| 国产成人精品毛片| 欧美日韩免费网站| 黄色一级片免费播放| 欧美三级第一页| 成人深夜直播免费观看| 国产玉足榨精视频在线观看| 一区二区三区在线高清| 国产又黄又粗又猛又爽的视频| 一区二区三区中文| 国产在线欧美日韩| 黑人精品视频| 日韩欧美国产wwwww| 日日摸天天添天天添破| 国产精品久久久久精k8| 妖精视频一区二区| 激情亚洲成人| 成人av免费电影| 欧美日韩电影免费看| 欧美美最猛性xxxxxx| 国产同性人妖ts口直男| 国产精品久久久久久久久图文区 | a天堂资源在线观看| 色综合久久久| 色综合亚洲精品激情狠狠| 亚洲风情第一页| 亚洲午夜免费视频| 成年人看的免费视频| 不卡高清视频专区| www精品久久| 久久精品高清| 久久一区二区三区av| 亚洲一区二区三区免费| 国产精品日韩久久久久| 最新97超碰在线| 欧美系列一区二区| 久久精品国产亚洲AV成人婷婷| 成人福利电影精品一区二区在线观看| 亚洲色图 在线视频| 亚洲欧美日韩精品一区二区| 免费日韩电影在线观看| 综合激情网...| 91免费综合在线| 久久久免费人体| 久久香蕉频线观| 国产特黄在线| 日韩精品免费在线播放| 亚洲国产精品久久久久久6q| 欧美精品一卡两卡| 日本三级一区二区三区| 欧美日韩一区二区在线播放| 国产在线观看成人| 亚洲一区在线观看免费 | 综合国产在线| 中文字幕综合在线观看| 日韩久久电影| 五月天婷亚洲天综合网鲁鲁鲁| av在线不卡精品| 欧美亚洲另类制服自拍| 不卡专区在线| 97色在线观看| 91在线观看| 中文字幕国产精品| 国产免费a∨片在线观看不卡| 日韩高清av在线| 少妇一区二区三区四区| 亚洲第一区在线| 日韩在线观看视频网站| 在线免费亚洲电影| 亚洲 欧美 日韩 在线| 色综合久久中文字幕| 成熟的女同志hd| 亚洲欧美日韩国产成人精品影院 | 国产欧美三级电影| 国产伦精品一区二区三区照片91| 91成人短视频| 精品国产综合| 一区二区三区日本视频| 午夜精品久久久久久久白皮肤| 日韩成人伦理| 午夜精品一区二区三区在线 | 亚洲精彩视频| 久久久久久久久久伊人| 欧美日韩一本| 国产三级精品网站| 热三久草你在线| 奇米四色中文综合久久| 色婷婷在线播放| 久久久久久久久久久国产| 98在线视频| 久久韩国免费视频| 天堂av最新在线| 97国产在线观看| 欧美成a人片在线观看久| 国产日本欧美一区二区三区在线| 激情综合五月| 精品久久久三级| 国产成人高清| 国产又粗又硬又长| 99国产精品久久久久久久| 国产日韩视频在线播放| 欧美日韩岛国| 日韩毛片在线免费看| 伊人久久婷婷| 成年人小视频网站| 国产一区二区在线观看视频| youjizz.com日本| 国产一区二区看久久| 影音先锋资源av| 国产婷婷一区二区| 欧美极品aaaaabbbbb| 国产精品麻豆99久久久久久| 欧美三级小视频| 亚洲欧美日韩小说| 成人18视频免费69| 亚洲第一成人在线| 中文字幕欧美人妻精品一区蜜臀| 一本到不卡免费一区二区| 一级特黄特色的免费大片视频| 91激情在线视频| 无码人妻久久一区二区三区不卡| 欧美日韩一区 二区 三区 久久精品| 精品国自产拍在线观看| 亚洲欧美综合v| 日本大胆在线观看| 国产精品一区二区电影| 亚洲精品动态| 欧美另类一区| 欧美日一区二区三区在线观看国产免| 91av俱乐部| 成人精品免费看| 成人涩涩小片视频日本| 色婷婷av一区二区三区软件 | 一区二区三区国产视频| 欧美1—12sexvideos| 国产精品永久免费观看| 偷窥自拍亚洲色图精选| 欧美激情www| 欧美日韩天堂| 男女视频在线观看网站| 国产精品欧美综合在线| 国产成人一级片| 亚洲国产精品va在线看黑人动漫 | 日韩一级中文字幕| 精品中文字幕乱| 91成人在线网站| 亚洲精品国产一区| 91精品综合久久久久久久久久久| 亚洲精品无人区| 欧美亚洲网站| 国产麻豆xxxvideo实拍| 亚洲午夜精品久久久久久久久| 国产又大又粗又长| 日韩一区在线视频| gay欧美网站| 乱一区二区三区在线播放| 亚洲麻豆视频| 少妇一级淫免费观看| 亚洲福中文字幕伊人影院| 亚洲卡一卡二卡三| 欧美激情国产精品| aaa国产精品视频| 日本一区二区三区四区在线观看 | 成年午夜在线| 久久精品一偷一偷国产| 久久久加勒比| 伊人久久青草| 中国女人久久久| 中文字幕人妻一区二区三区| 天天综合天天做天天综合| 免费国产黄色片| 91黑丝在线观看| 妖精视频一区二区三区免费观看| 91av资源网| 国产伦精品一区二区三区免费迷| 久久久久久久久久97| 精品国产乱码久久久久酒店| 日批视频在线播放| 7777kkkk成人观看| 国产不卡av一区二区| 91色国产在线| av电影天堂一区二区在线| 国产91在线播放九色| 欧美日韩精品欧美日韩精品一| 女人18毛片水真多18精品| 欧美激情乱人伦一区| 欧美顶级毛片在线播放| 日日碰狠狠躁久久躁婷婷| 国产精品网曝门| xxxwww在线观看| 2019最新中文字幕| 成人同人动漫免费观看| 欧美国产在线一区| 欧美国产日本韩| 99在线观看精品视频| 高清一区二区三区日本久| 伊人久久大香| 国产女主播自拍| 黄色精品一二区| 国产一级特黄a高潮片| 亚洲美女喷白浆| 亚洲午夜剧场| 日韩小视频在线播放| 国产精品一区二区免费不卡| 久久久综合久久久| 91精品国产91综合久久蜜臀| 精品日韩av| 视频一区不卡| 岛国精品在线播放| 国产精品99久久久久久成人| 亚洲国产精品久久久久| 91九色综合| 东北少妇不带套对白| 欧美激情一区在线观看| 日本视频在线观看免费| 日韩中文字幕国产精品| 久久99精品国产自在现线| 91热这里只有精品| 亚洲国产精品久久不卡毛片| 中文字幕在线视频区| 国模精品娜娜一二三区| 久久精品国产亚洲一区二区三区 | 亚洲精选免费视频|