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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Openfire XMPP Smack RTC IM 即时通讯 聊天 MD

發布時間:2023/11/27 生活经验 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Openfire XMPP Smack RTC IM 即时通讯 聊天 MD 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Markdown版本筆記我的GitHub首頁我的博客我的微信我的郵箱
MyAndroidBlogsbaiqiantaobaiqiantaobqt20094baiqiantao@sina.com

Openfire XMPP Smack RTC IM 即時通訊 聊天 MD


目錄

目錄
簡介
Openfire 簡介
相關的幾個名詞
Smack
Spark
JID
XMPP
Openfire 安裝配置
Stanza 節
共同屬性
Presence 在線狀態
Message 傳遞消息
IQ 請求響應
測試代碼
connect 過程
login 過程
獲取通訊錄
告訴服務器在線狀態
判斷是否在線
發送消息
測試案例代碼
項目結構
MainActivity
常用功能封裝的工具欄

簡介

Demo地址:https://github.com/baiqiantao/OpenFireTest.git
官網
官方文檔
OpenFire下載

Openfire 簡介

  • Openfire是一個根據開源Apache許可證授權的實時協作服務器 real time collaboration (RTC)。它使用唯一廣泛采用的即時消息開放協議XMPP(Jabber)。 Openfire非常容易設置和管理,但提供堅如磐石的安全性和性能。
  • Openfire是一個功能豐富即時消息和跨平臺實時協作服務器,使用XMPP協議提供全面的群聊和即時消息服務
  • OpenFire是采用Java編程語言開發的實時協作服務器,可以輕易的構建高效率的即時通信服務器,安裝和使用簡單,利用 Web 進行管理,單臺服務器可支持上萬并發用戶

相關的幾個名詞

簡單說,OpenFire 是服務器,XMPP 是協議,Smack 是類庫,Spark 是客戶端。

Smack

GitHub
Flowdalic/asmack

  • Smack 是一個基于 XMPP 協議的 Java 實現,提供一套可擴展的API,與 OpenFire 進行通信。
  • Smack 是一個開源,易于使用的 XMPP 客戶端類庫,可以實現即時通訊和聊天。
  • Smack 是Spark項目的核心。

優點:

  • 簡單,功能強大,只需短短幾行代碼就可以向用戶發送文本消息;
  • 不像其他類庫那樣強制你進行包級別的編碼,Smack提供了智能的、更高級的構造,像Chat和Roster類,可以讓你進行更高效的編程;
  • 你不需要熟悉 XMPP XML 格式,甚至不需要熟悉XML;
  • 提供了簡單的機器到機器通訊,允許在每個消息中設置任意數量的屬性,包括java對象;
  • Apache許可下的開源類庫,這意味著使用者可以將Smack整合進商業的或者非商業的應用中。

缺點是其API并非為大量并發用戶設計,每個客戶要1個線程,占用資源大。

Spark

  • Spark 相當與電腦版QQ,通過 smack 與 openfire 進行通信。
  • Spark 是一個 XMPP 協議通信聊天的CS端的IM軟件,它可以通過 openfire 進行聊天對話。
<message from="admin@myopenfire.com" to="bqt@myopenfire.com">消息內容</message>

JID

  • 基于歷史原因, 一個XMPP實體的地址稱為Jabber IdentifierJID,它用來標示XMPP網絡中的各個XMPP實體。
  • 鑒于協議的分布式特征, JID 應包含聯系到用戶所需的所有信息。
  • 個人認為可以把JID理解為Email地址,就比較好理解了。
  • 一個合法的JID包括節點名user、域名domain、資源名resource,其中 user 和 resource 是可有可無的,domain 是必須的。domain和user部分是不分大小寫的,但是resource區分大小寫。
    • domainpart 通常指網絡中的網關或者服務器
    • localpart(user、node) 通常表示一個向服務器或網關請求和使用網絡服務的實體(比如一個客戶端),當然它也能夠表示其他的實體(比如在多用戶聊天系統中的一個房間)。
    • resourcepart:通常表示一個特定的會話(與某個設備),連接(與某個地址),或者一個附屬于某個節點ID實體相關實體的對象(比如多用戶聊天室中的一個參加者)。
  • JID的格式為:jid = [ localpart "@" ] domainpart [ "/" resourcepart ],例如:
    • stpeter@jabber.org:表示服務器jabber.org上的用戶stpeter
    • room@service:一個用來提供多用戶聊天服務的特定的聊天室。這里 room 是聊天室的名字,service 是多用戶聊天服務的主機名
    • room@service/nick:加入了聊天室的用戶nick的地址。這里 nick 是用戶在聊天室的昵稱

XMPP

Extensible Messaging and Presence Protocol,可擴展通訊和表示協議

  • XMPP 是基于 XML 的協議,這表明 XMPP 是可擴展的。
  • XMPP 包含了針對服務器端的軟件協議,用于即時消息以及在線現場探測。
  • XMPP 的前身是Jabber(1998 年),一個開源形式組織產生的網絡即時通信協議。
  • XMPP 是一個由IETF標準化的開放協議,由XMPP標準基金會支持和擴展。

XMPP是一種基于標準通用標記語言的子集XML的協議,它繼承了在XML環境中靈活的發展性。因此,基于XMPP的應用具有超強的可擴展性。經過擴展以后的XMPP可以通過發送擴展的信息來處理用戶的需求,以及在XMPP的頂端建立如內容發布系統和基于地址的服務等應用程序。而且,XMPP包含了針對服務器端的軟件協議,使之能與另一個進行通話,這使得開發者更容易建立客戶應用程序或給一個配好系統添加功能。

優點:開放、可擴展、標準、證實可用、分散、安全
缺點 :數據負載過重,沒有二進制傳輸

基本網絡結構

  • XMPP中定義了三個角色,客戶端,服務器,網關,通信能夠在這三者的任意兩個之間雙向發生。
  • 服務器同時承擔了客戶端信息記錄,連接管理和信息的路由功能。
  • 網關承擔著與異構即時通信系統的互聯互通,異構系統可以包括SMS,MSN,ICQ等。
  • 基本的網絡形式是單客戶端通過TCP/IP連接到單服務器,然后在之上傳輸XML。

XMPP 工作流程

  • 節點連接到服務器
  • 服務器利用本地目錄系統中的證書對其認證
  • 節點指定目標地址,讓服務器告知目標狀態
  • 服務器查找、連接并進行相互認證
  • 節點之間進行交互

XMPP核心協議通信的基本模式就是先建立一個stream,然后協商一堆安全之類的東西,中間通信過程就是客戶端發送XML Stanza(節點),一個接一個的。服務器根據客戶端發送的信息以及程序的邏輯,發送XML Stanza給客戶端。但是這個過程并不是一問一答的,任何時候都有可能從一方發信給另外一方。通信的最后階段是</stream>關閉流,關閉TCP/IP連接。

傳輸的內容
傳輸的是與即時通訊相關的指令。在以前這些命令要么用2進制的形式發送(比如QQ),要么用純文本指令加空格加參數加換行符的方式發送(比如MSN)。而XMPP傳輸的即時通訊指令的邏輯與以往相仿,只是協議的形式變成了XML格式的純文本。這不但使得解析容易了,人也容易閱讀了,方便了開發和查錯。

XMPP 的核心部分就是一個在網絡上分片段發送 XML 的流協議。這個流協議是 XMPP 的即時通訊指令的傳遞基礎,可以說 XMPP 用 TCP 傳的是 XML 流。

真實通訊案例
Xmpp協議是建立在xml的基礎上的,所以,看起來,xmpp協議就像一個xml。

客戶端 8049a646c63e65e8 發出去的消息:

<message from='8049a646c63e65e8@oatest.dgcb.com.cn/phone' id='5U6Mk-5' to='903e652d2334628a@oatest.dgcb.com.cn' type='chat'><body>{"fromId":"8049a646c63e65e8","fromName":"韓大東","messageType":1,"secret":false,"textContent":"你好","toName":"鄭西風","toUserID":"903e652d2334628a"}</body><request xmlns='urn:xmpp:receipts'/>
</message>

客戶端 8049a646c63e65e8 接收到的消息:

<message from="903e652d2334628a@oatest.dgcb.com.cn/phone" id="Bw4c9-4" to="8049a646c63e65e8@oatest.dgcb.com.cn" type="chat"><body>{"fromId":"903e652d2334628a","fromName":"鄭西風","messageType":1,"secret":false,"textContent":"你好"}</body><request xmlns="urn:xmpp:receipts"/><send time="2018-10-19 16:08:21:999" xmlns="icitic:msg:single"/>
</message>

其實 XMPP 是一種很類似于http協議的一種數據傳輸協議,用戶只需要明白它接收的類型,并理解它返回的類型,就可以很好的利用xmpp來進行數據通訊。

目前不少IM應用系統如Google公司的Google Talk以及Jive Messenger等開源應用,都是遵循XMPP協議集而設計實現的,這些應用具有很好的互通性。

Openfire 安裝配置

安裝時除了修改一下安裝路徑,其他一路Next就Ok了。

安裝完畢后會自動啟動Openfire服務并自動打開 配置頁面 (可能需要手動刷新一下)。也可以通過雙擊 \Openfire\bin\openfire.exe\Openfire\bin\openfired.exe 啟動Openfire服務后手動打開配置頁面。

然后按照指引設置 Openfire 服務器:

  • 選擇語言:中文簡體
  • 配置服務器域名【127.0.0.1】

  • 選擇數據庫

  • 選擇特性配置,默認即可

  • 設置管理員帳戶【0909082401@163.com】【123456a】

  • 提示安裝完成,點擊登錄管理員控制臺頁面【admin】【123456a】

  • 進入后可以看到服務器名稱等信息【127.0.0.1】

  • 創建用戶【admin】【baiqiantao】【bqt】【test】

  • 安裝spark客戶端,這個spark僅僅是拿來測試用的。

至此代碼以外的環境已經配置好了。

Stanza 節

Xml是由節點構成的,而基于xml的xmpp協議中與通信有關三個最核心的節(Stanza)是:<message>、<presence>、<iq>,可以通過組織不同的節來達到各式各樣不同的通訊目的。接下來就對這些Stanza做一個大致的了解。

共同屬性

每個節都有其屬性,雖然不同的節其屬性各有不同,但是一些基本的屬性是這些所有的節所共同的以下這些是他們的共同屬性。

  • from
    表示Stanza的發送方,在發送Stanza時,一般來說不推薦設定,服務器會自動設定正確的值,如果你設定了不正確的值,服務器將會拒收你的Stanza信息。

  • to
    表示Stanza的接收方。這個節點一般是自己設置的,若到達服務器的數據中沒收設置該屬性,則服務器會認為這條信息是發送給自己的。

  • type
    指定Stanza的類型。
    這個節與前兩個不同,設置的值不可以統一而論,不同的節有不同的設定值,每種Stanza都有固定的幾種可能的設定值。
    雖然不同節點的type屬性各有不同,但是都有一個error類型,表示這是一條錯誤信息,服務器接收到這種類型的信息的時候不需要作出任何的回應。

  • id
    用于標志唯一的一條特定信息,表示一個特定的請求。
    在節中,這個屬性是必須要指定的,但是在其他兩個Stanza中是一個可選屬性。

Presence 在線狀態

Presence Stanza 用來控制和表示實體的在線狀態,可以展示離線、在線、離開、不能打擾等復雜狀態,另外,還能被用來建立和結束在線狀態的訂閱。

除了類型信息外,Presence還包含其他一些可選的屬性:

  • Status: 用于表示用戶狀態的自定義文本,例如:外出吃飯
  • Priority: 一個表示發送者資源優先級的非負數
  • Mode: 表示五種狀態之一

案例
<presence/> 設定用戶狀態為在線
<presence type="unavailable"/> 設定用戶狀態為離線

<presence><show>away</show><status>at the ball</status>
</presence> 

用于顯示用戶狀態的詳細信息。上面的例子表明用戶因為at the ball在離開狀態。

  • <show> 標簽在presence節點中最多出現一次,取值可以為Presence.Mode中的某一個。
  • <status>標簽用于顯示額外信息
<presence><status>touring the countryside</status><priority>10</priority>
</presence>

在這個節中,出現了一個<priority>標簽,表示現在連接的優先級。每個連接可以設置從-128到127的優先級,默認是設置為0,用戶可以在這個標簽里修改相應的優先級。

在線狀態預定
首先我們來看一個例子:

<presencefrom="william_duan@jabber.org"to="test_account@jabber.org"type="subscribe"/>
<presencefrom="test_account@jabber.org"to="william_duan@jabber.org"type="subscribed"/>

通過上述交互,william_duan 就能看到 test_account 的在線狀態,并能接收到 test_account 的在線狀態通知了(例如上線提醒功能)。

Presence.Type

package org.jivesoftware.smack.packet;
public enum Presence.Type {available, //【在線,可接收消息】The user is available to receive messages (default).unavailable,//【離線,不可接收消息】The user is unavailable to receive messages.subscribe,//【申請添加對方為好友】Request subscription to recipient's presence.subscribed, //【同意對方添加自己為好友】Grant subscription to sender's presence.unsubscribe, //【刪除好友的申請】Request removal of subscription to sender's presence.unsubscribed,//【拒絕添加對方為好友】Grant removal of subscription to sender's presence.error,//【錯誤】The presence stanza(/packet) contains an error message.probe,;//【賬號是否存在】A presence probe as defined in section 4.3 of RFC 6121public static Type fromString(String string) {return Type.valueOf(string.toLowerCase(Locale.US));}
}

Presence.Mode

package org.jivesoftware.smack.packet;
public enum Presence.Mode {chat, //【交談中】,Free to chat.available, //【在線】Available (the default).away, //【離開】,Away.xa, //【離開一段時間】,Away for an extended period of time.dnd; //【請勿打擾】,Do not disturb.public static Presence.Mode fromString(String string) {return Presence.Mode.valueOf(string.toLowerCase(Locale.US));}
}

Message 傳遞消息

用于在用戶之間傳遞信息,這消息可以是單純的聊天信息,也可以某種格式化的信息。

message節點信息是傳遞之后就被忘記的。當消息被送出之后,發送者是不管這個消息是否已經送出或者什么時候被接收到。但是通過擴展協議,可以改變這樣一種狀況。

案例
私人聊天信息:

<messagefrom="william_duan@jabber.org"to="test_account@jabber.org"type="chat"><body>Come on</body><thread>23sdfewtr234weasdf</thread>
</message> 

多人聊天信息:

<messagefrom="test_account@jabber.org"to="william_duan@jabber.org"type="groupchat"><body>welcome</body>
</message>

上面的兩個例子都包含了一個<type>標簽,這個標簽表明了消息的類型,可以取 Message.Type 中的任一值。

<body>標簽里面是具體的消息內容。

Message.Type

package org.jivesoftware.smack.packet;
public enum Message.Type {normal,//【廣播】(Default) a normal text message used in email like interface.chat,//【單聊】Typically short text message used in line-by-line chat interfaces.groupchat,//【群聊】Chat message sent to a groupchat server for group chats.headline,//【通知,不需要回應】Text message to be displayed in scrolling marquee滾動選框 displays.error;//【錯誤】indicates a messaging error. error消息為系統自動發送的,往往是由于錯誤發送消息public static Type fromString(String string) {return Type.valueOf(string.toLowerCase(Locale.US));}
}

IQ 請求響應

  • IQ Stanza 主要是用于Info/Query模式的消息請求,他和Http協議比較相似。
  • IQ節點需要有回應
  • 可以發出get以及set請求,就如同http中的GET以及POST
  • result以及error兩種回應。

案例
william_duan 請求自己的聯系人列表:

<iqfrom="william_duan@jabber.org/study"id="roster1"type="get"><query xmlns="jabber:iq:roster"/>
</iq> 

請求發生錯誤:

<iqid="roster1"to="william_duan@jabber.org/study"type="error"><query xmlns="jabber:iq:roster"/><error type="cancel"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error>
</iq>

請求成功,返回 william_duan 的聯系人列表。每一個<item>標簽代表了一個聯系人信息:

<iqid="roster1"to="william_duan@jabber.org/study"type="error"><query xmlns="jabber:iq:roster"/><itemname="one"jid="account_one@jabber.org"/><itemname="two"jid="account_two@jabber.org"/>
</iq> 

IQ.Type

public enum IQ.Type {get, //【請求消息】The IQ stanza requests information, inquires about what data is needed in order to complete further operations, etc.set, //【設置消息】The IQ stanza provides data that is needed for an operation to be completed, sets new values, replaces existing values, etc.result, //【成功】The IQ stanza is a response to a successful get or set request.error,; //【失敗】The IQ stanza reports an error that has occurred regarding processing or delivery of a get or set request.public static IQ.Type fromString(String string) {return IQ.Type.valueOf(string.toLowerCase(Locale.US));}
}

測試代碼

Demo地址:https://github.com/baiqiantao/OpenFireTest.git

XMPPConnection的連接需要首先通過XMPPTCPConnectionConfiguration.builder()配置你在Openfire設置的配置,然后根據配置構造一個 XMPPTCPConnection ,以后所有操作基本都需要用到這個 XMPPTCPConnection 。

connection = new XMPPTCPConnection(configuration);

通過了上面的配置后,咱們可以登錄Openfire系統了,相當簡單:

XMPPUtils.getConnection().login(username, password);

下面我們重點分析下登錄過程的報文內容以及一些最常用的API。

connect 過程

在建立了Socket后,client會向服務器發出一條xml:

<stream:stream xmlns:stream='http://etherx.jabber.org/streams'from='8049a646c63e65e8@oatest.dgcb.com.cn'to='oatest.dgcb.com.cn'version='1.0'xmlns='jabber:client'xml:lang='en'>

服務器解析到上面的指令后,會返回用于告訴client可選的SASL方式

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"from="oatest.dgcb.com.cn"id="36ebm4blnf"version="1.0"xmlns="jabber:client"xml:lang="en"><stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>SCRAM-SHA-1</mechanism><mechanism>CRAM-MD5</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><ver xmlns="urn:xmpp:features:rosterver"/><register xmlns="http://jabber.org/features/iq-register"/></stream:features>

至此,connect 算是完成了,此時會回調 ConnectionListenerconnected 方法。

login 過程

XMPPUtils.getConnection().login(username, password);

1、客戶端選擇PLAIN認證方式

<auth mechanism='PLAIN'xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>ADgwNDlhNjQ2YzYzZTY1ZTgAQkRFNEM3QzBGMzdENEZGRTlENDlGNDcwMTdFNUJCRjc=
</auth>

服務器通過計算加密后的密碼后,服務器將返回

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

2、當客戶端收到以上命令后,將首次發起連接的id發送到服務器

<stream:stream xmlns:stream='http://etherx.jabber.org/streams'from='8049a646c63e65e8@oatest.dgcb.com.cn'id='36ebm4blnf'to='oatest.dgcb.com.cn'version='1.0'xmlns='jabber:client'xml:lang='en'>

這時服務器會返回如下內容說明此時已經成功綁定了當前的Socket

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"from="oatest.dgcb.com.cn"id="36ebm4blnf"version="1.0"xmlns="jabber:client"xml:lang="en"><stream:features><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><ver xmlns="urn:xmpp:features:rosterver"/><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"><optional/></session><sm xmlns='urn:xmpp:sm:2'/><sm xmlns='urn:xmpp:sm:3'/></stream:features>

3、壓縮
3.1、客戶端在接收到如上的內容后會告訴服務器開啟壓縮

項目中沒有使用壓縮,所以下面的過程不存在,以下為參考別人的案例

<compress xmlns='http://jabber.org/protocol/compress'><method>zlib</method></compress>

服務器返回

<compressed xmlns='http://jabber.org/protocol/compress'/>

3.2、客戶端收到服務器的響應命令后,重新建立一個Socket,發送指令

<stream:stream xmlns='jabber:client'       to='server domain' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' from='username@server domain'  id='c997c3a8' xml:lang='en'>

服務器將返回,不知道你有沒有發現,這里的id還是那個id

<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="im" id="c997c3a8" xml:lang="en" version="1.0"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>JIVE-SHAREDSECRET</mechanism></mechanisms><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>

4、客戶端發送綁定Socket的指令:

<iqid='SG6jR-3'type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>phone</resource></bind>
</iq>

服務器返回綁定了具有指定 JID 的客戶端

<iqid="SG6jR-3"to="oatest.dgcb.com.cn/36ebm4blnf"type="result"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>8049a646c63e65e8@oatest.dgcb.com.cn/phone</jid></bind>
</iq>

5、開啟一個session

項目中沒有開啟一個session的邏輯,所以下面的過程不存在,以下為參考別人的案例

<iq id='b86j8-6' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>

這時服務器返回

<iq type="result" id="b86j8-6" to="c997c3a8@im/c997c3a8"/>

6、認證
因為項目中沒有開啟認證,所以這里沒有報文通訊,只有如下日志:

至此,客戶端的登錄過程算是完成了。

注意,connect 和 login 都是同步操作,所以在 login(username, password) 方法調用以后,如果沒有報異常,就是登陸成功了。

獲取通訊錄

登陸以后接著會自動發送一條獲取通訊錄的指令,并會將通訊錄緩存起來,所以以后再獲取通訊錄時,并不需要訪問網絡。

<iqid='gZYnq-5'type='get'><query xmlns='jabber:iq:roster'></query>
</iq>

服務器將返回

<iqid="SG6jR-5"to="8049a646c63e65e8@oatest.dgcb.com.cn/phone"type="result"><query ver="-491295515"xmlns="jabber:iq:roster"><itemname="李**"jid="0347a8a25e9074b0@oatest.dgcb.com.cn"subscription="to"/><itemjid="903e652d2334628a@oatest.dgcb.com.cn"subscription="from"/><itemask="subscribe"jid="28af56d053cbbf3e@oatest.dgcb.com.cn"subscription="none"/></query>
</iq>

此過程完成以后會回調 RosterListenerentriesAdded 方法。

告訴服務器在線狀態

雖然已經登錄了,但是還需要告訴服務器自己的狀態,否則服務器不會認為你是在線狀態,這時你可能就收不到其他好友發來的消息(我們我們項目中有集成離線推送功能,如果沒有告訴服務器你在笑,服務器會走離線消息推送的邏輯。)

XMPPUtils.getConnection().sendStanza(presence);

客戶端發送 presence 消息告訴服務器自己在線:

<presencefrom='8049a646c63e65e8@oatest.dgcb.com.cn/phone'id='91kqC-27'><status>IchatMM</status><priority>0</priority><c hash='sha-1'node='http://www.igniterealtime.org/projects/smack'ver='NfJ3flI83zSdUDzCEICtbypursw='xmlns='http://jabber.org/protocol/caps'/>
</presence>

服務器響應:

<presencefrom="c53706e24ce32f72@oatest.dgcb.com.cn/pc"to="8049a646c63e65e8@oatest.dgcb.com.cn/phone"><priority>0</priority><c hash="sha-1"node="http://camaya.net/gloox"ver="9ZtEa+bYQasYo2pVBGT9ShIT+Yc="xmlns="http://jabber.org/protocol/caps"></c>
</presence>

收到響應后,會回調 RosterListenerpresenceChanged 方法,此后,就可以愉快的玩耍了。

判斷是否在線

服務器會定時(默認3分鐘)主動發送一條 ping 消息,以確定客戶端是否在線:

PingManager.getInstanceFor(connection).setPingInterval(60);//ping消息間隔

<iqfrom="oatest.dgcb.com.cn"id="553-595"to="8049a646c63e65e8@oatest.dgcb.com.cn/phone"type="get"><ping xmlns="urn:xmpp:ping"/>
</iq>

客戶端響應:

<iqid='553-595'to='oatest.dgcb.com.cn'type='result'></iq>

到此,整個登錄流程已經成功了,接下來可以做一些用戶信息的獲取等操作。

發送消息

//發送方式一,簡單的發送文本消息
ChatManager.getInstanceFor(XMPPUtils.getConnection()).createChat(to).sendMessage(text);
//發送方式二,發送一個Message對象,可包含一些信息,一般使用這種方式
XMPPUtils.getConnection().sendStanza(msg);

除去消息內容后的日志:

14:51:02.365 客戶端A I/bqt: 【chatCreated】
14:51:02.366 客戶端A D/SMACK: SENT (0)
14:51:02.399 客戶端A D/SMACK: RECV (0)
14:51:02.400 客戶端A I/bqt: 【processPacket】
14:51:02.402 客戶端A I/bqt: 【processMessage】
14:51:02.404 客戶端A D/SMACK: RECV (0)
14:51:02.404 客戶端B D/SMACK: RECV (0)
14:51:02.407 客戶端A I/bqt: 【processPacket】
14:51:02.407 客戶端A I/bqt: 【processMessage】
14:51:02.409 客戶端B I/bqt: 【processPacket】
14:51:02.410 客戶端B I/bqt: 【chatCreated】
14:51:02.411 客戶端B I/bqt: 【processMessage】
14:51:02.412 客戶端B I/bqt: 消息類型:chat

1、客戶端A發送消息:

<messagefrom='8049a646c63e65e8@oatest.dgcb.com.cn/phone'id='nCRIE-44'to='903e652d2334628a@oatest.dgcb.com.cn/phone'type='chat'><body>你好,我是包青天</body><thread>6828a752-cfae-4149-9d4d-c8fb83a17175</thread>
</message>

客戶端收到服務器的回執(msgId相同):

<messagefrom="903e652d2334628a@oatest.dgcb.com.cn/phone"to="8049a646c63e65e8@oatest.dgcb.com.cn/phone"><received msgId="nCRIE-44"status="1"time="2018-10-20 14:50:16:566"xmlns="urn:xmpp:receipts"/>
</message>

2、然后,客戶端B會收到客戶端A發送的消息(id相同):

<messagefrom="8049a646c63e65e8@oatest.dgcb.com.cn/phone"id="nCRIE-44"to="903e652d2334628a@oatest.dgcb.com.cn/phone"type="chat"><body>你好,我是包青天</body><thread>6828a752-cfae-4149-9d4d-c8fb83a17175</thread><send time="2018-10-20 14:50:16:572"xmlns="icitic:msg:single"/>
</message>

客戶端A也會收到的回執消息(id后面拼接了mutisingle):

<messagefrom="8049a646c63e65e8@oatest.dgcb.com.cn"id="nCRIE-44mutisingle"to="8049a646c63e65e8@oatest.dgcb.com.cn"type="chat"><subject>903e652d2334628a@oatest.dgcb.com.cn</subject><body>你好,我是包青天</body><send time="2018-10-20 14:50:16:571"xmlns="icitic:msg:single"/>
</message>

測試案例代碼

項目結構

implementation 'org.igniterealtime.smack:smack-android:4.1.4'
implementation 'org.igniterealtime.smack:smack-tcp:4.1.4'
implementation 'org.igniterealtime.smack:smack-im:4.1.4'
implementation 'org.igniterealtime.smack:smack-extensions:4.1.4'

MainActivity

public class MainActivity extends ListActivity {private boolean switchUser = false;private EditText etAccount, etPassword, etChat;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);String[] array = {"初始化","登錄","發送在線狀態消息","發消息","獲取好友信息","創建聊天室","加入聊天室","邀請好友進入聊天室","注銷登錄","",};setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Arrays.asList(array)));etAccount = new EditText(this);etPassword = new EditText(this);etChat = new EditText(this);etAccount.setText(switchUser ? "8049a646c63e65e8" : "903e652d2334628a");etPassword.setText(switchUser ? "1E6210BB50614D978F4758B2DC9D76C9" : "40C61DE3492C41B1846281833434D997");etChat.setText(switchUser ? "903e652d2334628a@oatest.dgcb.com.cn/phone" : "8049a646c63e65e8@oatest.dgcb.com.cn/phone");getListView().addFooterView(etAccount);getListView().addFooterView(etPassword);getListView().addFooterView(etChat);//要聊天的用戶的ID}@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {String account = etAccount.getText().toString();String password = etPassword.getText().toString();String jid = etChat.getText().toString();new Thread(() -> testApi(position, account, password, jid)).start();}private void testApi(int position, String account, String password, String jid) {switch (position) {case 0:XMPPUtils.init(account, password);//初始化break;case 1:XMPPUtils.login(account, password);//登錄break;case 2:XMPPUtils.setOnLineStatus();//在線break;case 3:XMPPUtils.sendMessage(account + "@oatest.dgcb.com.cn/phone", jid, "你好,我是包青天");//發消息break;case 4:XMPPUtils.getMyFriends();//獲取好友信息break;case 5:XMPPUtils.createMucRoom(jid, "包青天");//創建聊天室break;case 6:XMPPUtils.joinChatRoom(jid, account);//加入聊天室break;case 7:XMPPUtils.inviteToTalkRoom(jid, account, password, "快來參加第二十八屆英雄大會");//邀請好友進入聊天室break;case 8:XMPPUtils.logout();//注銷登錄break;default:break;}}
}

常用功能封裝的工具欄

public class XMPPUtils {private static XMPPTCPConnection connection;/*** 初始化*/public static synchronized void init(CharSequence username, String password) {if (connection == null) {//初始化XMPPTCPConnection相關配置XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder().setUsernameAndPassword(username, password)//設置登錄openfire的用戶名和密碼.setServiceName("oatest.dgcb.com.cn")//設置服務器名稱.setHost("oatest.dgcb.com.cn")//設置主機地址.setPort(25222)//設置端口號.setResource("phone") //默認為Smack.setDebuggerEnabled(true)//是否查看debug日志//**********************************************  以下為進階配置  *************************************************.setConnectTimeout(10 * 1000)//設置連接超時的最大時間.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)//設置安全模式,關閉安全模式.setCompressionEnabled(false) //開啟通訊壓縮,開啟后傳輸的流量將節省90%.setSendPresence(false).setCustomSSLContext(getSSLContext()) //自定義的TLS登錄.setHostnameVerifier((hostname, session) -> true).build();connection = new XMPPTCPConnection(configuration);connection.setFromMode(XMPPConnection.FromMode.USER);connection.addConnectionListener(new MyConnectionListener()); //監聽connect狀態connection.addAsyncStanzaListener(new MyStanzaListener(), StanzaTypeFilter.MESSAGE);// 注冊包的監聽器PingManager.getInstanceFor(connection).setPingInterval(60);//ping消息間隔//SASL認證SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");SASLAuthentication.blacklistSASLMechanism(SASLPlainMechanism.DIGESTMD5);SASLAuthentication.registerSASLMechanism(new SASLPlainMechanism());Roster.getInstanceFor(connection).addRosterListener(new MyRosterListener());ChatManager.getInstanceFor(connection).addChatListener(new MyChatManagerListener()); //監聽與聊天相關的事件MultiUserChatManager.getInstanceFor(connection).addInvitationListener(new MyInvitationListener()); //被邀請監聽}}private static SSLContext getSSLContext() {SSLContext context = null;try {context = SSLContext.getInstance("TLS");context.init(null, new TrustManager[]{new TLSUtils.AcceptAllTrustManager()}, new SecureRandom());} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (KeyManagementException e) {e.printStackTrace();}return context;}public static XMPPTCPConnection getConnection() {return connection;}/*** 登錄*/public static void login(CharSequence username, String password) {try {if (!XMPPUtils.getConnection().isConnected()) {XMPPUtils.getConnection().connect();}if (XMPPUtils.getConnection().isConnected()) {Log.i("bqt", "開始登錄");XMPPUtils.getConnection().login(username, password);Log.i("bqt", "登錄成功");} else {Log.i("bqt", "登錄失敗");}} catch (SmackException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (XMPPException e) {e.printStackTrace();}}/*** 告訴服務器登錄狀態*/public static void setOnLineStatus() {if (XMPPUtils.getConnection().isAuthenticated()) {try {Presence presence = new Presence(Presence.Type.available);presence.setStatus("IchatMM"); //顯示額外信息,內容根據需求可隨意定制presence.setPriority(0); //連接的優先級XMPPUtils.getConnection().sendStanza(presence);} catch (SmackException.NotConnectedException e) {e.printStackTrace();}}}/*** 注銷登錄*/public static void logout() {if (!XMPPUtils.getConnection().isConnected()) {XMPPUtils.getConnection().disconnect();}}/*** 發消息*/public static void sendMessage(String from, String to, String text) {try {ChatManager.getInstanceFor(XMPPUtils.getConnection()).createChat(to).sendMessage(text);//直接發送一條文本/*Message msg = new Message(to, Message.Type.chat);msg.setStanzaId(System.currentTimeMillis() + "");msg.setFrom(from);msg.setBody(text);XMPPUtils.getConnection().sendStanza(msg);//發送一個Message對象,可包含一些信息,一般使用后者*/} catch (SmackException.NotConnectedException e) {e.printStackTrace();}}/*** 獲取好友信息*/public static void getMyFriends() {//并不需要訪問網絡,因為在登錄后已經拿到用戶的通訊錄了,這里是直接從緩存中讀取的Set<RosterEntry> set = Roster.getInstanceFor(XMPPUtils.getConnection()).getEntries();for (RosterEntry entry : set) {Log.i("bqt", "JID:" + entry.getUser() + ",Name:" + entry.getName());}}/*** 創建聊天室*/public static void createMucRoom(String jid, String nickname) {try {MultiUserChat muc = MultiUserChatManager.getInstanceFor(XMPPUtils.getConnection()).getMultiUserChat(jid);muc.create(nickname);//昵稱Form form = muc.getConfigurationForm();Form submitForm = form.createAnswerForm();for (FormField field : form.getFields()) {if (!FormField.Type.hidden.equals(field.getType()) && field.getVariable() != null) {submitForm.setDefaultAnswer(field.getVariable());}}List<String> list = new ArrayList<>();list.add("20");List<String> owners = new ArrayList<>();owners.add("guochen@192.168.0.245");submitForm.setAnswer("muc#roomconfig_roomowners", owners);submitForm.setAnswer("muc#roomconfig_maxusers", list);submitForm.setAnswer("muc#roomconfig_roomname", "room01");submitForm.setAnswer("muc#roomconfig_persistentroom", true);submitForm.setAnswer("muc#roomconfig_membersonly", false);submitForm.setAnswer("muc#roomconfig_allowinvites", true);submitForm.setAnswer("muc#roomconfig_enablelogging", true);submitForm.setAnswer("x-muc#roomconfig_reservednick", true);submitForm.setAnswer("x-muc#roomconfig_canchangenick", false);submitForm.setAnswer("x-muc#roomconfig_registration", false);muc.sendConfigurationForm(submitForm);} catch (XMPPException.XMPPErrorException e) {e.printStackTrace();} catch (SmackException e) {e.printStackTrace();}}/*** 加入聊天室*/public static void joinChatRoom(String jid, String nickname) {try {MultiUserChat muc = MultiUserChatManager.getInstanceFor(XMPPUtils.getConnection()).getMultiUserChat(jid);muc.join(nickname);} catch (SmackException.NoResponseException e) {e.printStackTrace();} catch (XMPPException.XMPPErrorException e) {e.printStackTrace();} catch (SmackException.NotConnectedException e) {e.printStackTrace();}}/*** 邀請好友進入聊天室*/public static void inviteToTalkRoom(String jid, String nickname, String user, String reason) {try {MultiUserChat muc = MultiUserChatManager.getInstanceFor(XMPPUtils.getConnection()).getMultiUserChat(jid);muc.addInvitationRejectionListener((invitee, rejectReason) -> Log.i("bqt", "拒絕了," + invitee + "," + rejectReason));muc.join(nickname);muc.invite(user, reason);} catch (SmackException.NotConnectedException e) {e.printStackTrace();} catch (SmackException.NoResponseException e) {e.printStackTrace();} catch (XMPPException.XMPPErrorException e) {e.printStackTrace();}}
}

2018-10-19

轉載于:https://www.cnblogs.com/baiqiantao/p/9819242.html

總結

以上是生活随笔為你收集整理的Openfire XMPP Smack RTC IM 即时通讯 聊天 MD的全部內容,希望文章能夠幫你解決所遇到的問題。

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

国产视频在线观看一区 | 99热播精品| 精品久久综合 | 国产成人免费 | 国产在线观看免费av | 中文字幕在线观看资源 | 激情开心站 | 国产高清日韩欧美 | 亚洲性视频 | 麻豆一精品传二传媒短视频 | av三级av| 国产精品69av| 一区二区三区在线看 | 亚洲一区黄色 | 黄色三级在线观看 | 日韩性片 | 国产精品麻豆视频 | 超碰在线cao | 91成人精品一区在线播放69 | 波多野结衣电影一区二区 | 亚洲国产成人精品在线 | 97成人免费 | 欧美精品久久久久久久久久丰满 | 成年人在线看视频 | 国产高清不卡一区二区三区 | 日韩午夜一级片 | www.看片网站 | 亚洲婷久久 | 久久免费视频这里只有精品 | 黄色免费看片网站 | 久久激情网站 | 99热精品免费观看 | 亚洲 欧美 成人 | 午夜久久网站 | 精品国产一区二区三区男人吃奶 | 在线你懂| 欧美一区二区在线免费看 | 国产精品igao视频网网址 | 日日干激情五月 | 麻豆视频一区 | 色停停五月天 | 国产一区二区播放 | 国产传媒一区在线 | 免费看色网站 | 国产精品美女999 | 亚洲精品国偷自产在线99热 | 色婷婷一区 | 精品一区二区三区在线播放 | 高潮久久久 | 欧美精品v国产精品 | 久久久国产精品电影 | 成人黄色免费观看 | 99精品一级欧美片免费播放 | 国产永久免费高清在线观看视频 | 欧美精品网站 | 成人久久久电影 | 五月婷婷天堂 | www.神马久久| 欧美午夜视频在线 | 精品国产电影 | 久久久国产精品一区二区中文 | 婷婷色影院 | 在线精品亚洲 | 国产精品黑丝在线观看 | 日本在线观看黄色 | 精品视频网站 | 免费在线观看成年人视频 | 色姑娘综合天天 | 99超碰在线观看 | 不卡中文字幕在线 | 国产视频2 | 中文字幕乱在线伦视频中文字幕乱码在线 | 国产999免费视频 | 特片网久久 | 久久不卡电影 | 亚洲影院天堂 | 有码中文字幕在线观看 | 中文字幕精品视频 | 91完整版在线观看 | 中文字幕日韩有码 | 天天综合在线观看 | 欧美日韩视频在线 | 日韩 精品 一区 国产 麻豆 | av激情五月 | www视频在线免费观看 | 午夜视频免费在线观看 | 久久久成人精品 | 国产一区二区播放 | 免费97视频 | 欧美视频二区 | 日韩高清dvd | 91大神dom调教在线观看 | 在线国产专区 | 国产精品24小时在线观看 | 久久久久久久久久伊人 | 中文字幕在线看视频 | 日韩一区二区三区免费电影 | av免费网站 | 婷婷中文字幕 | 精品国产91亚洲一区二区三区www | 欧美日韩国产在线观看 | 婷色在线 | 久久精品视频一 | 中文字幕在线观看三区 | 人人舔人人插 | 四川bbb搡bbb爽爽视频 | 成人一级影视 | 亚洲另类xxxx | www.五月婷婷.com | 国产露脸91国语对白 | 最近更新的中文字幕 | 中文字幕有码在线播放 | 国产精品亚洲片在线播放 | 成人av电影免费在线播放 | 亚洲一区视频免费观看 | 日韩在线观看视频一区二区三区 | 91av在线播放视频 | 黄在线免费看 | 国产成人99久久亚洲综合精品 | 久久夜色精品国产欧美乱 | 97日日碰人人模人人澡分享吧 | www久久com| a黄色影院| 91手机视频 | 精品九九九九 | 国产成人精品国内自产拍免费看 | 午夜av免费在线观看 | 国产成人精品一区二三区 | 中文字幕一区二区三区四区久久 | 国产黄色免费 | 四虎在线影视 | 草草草影院 | 成年人国产精品 | 久久精精品 | 三上悠亚一区二区在线观看 | 色婷婷在线观看视频 | 91成版人在线观看入口 | 奇米影视四色8888 | 精品1区二区 | 在线观看视频国产一区 | 免费观看www小视频的软件 | 亚洲午夜精品久久久久久久久久久久 | 久操久| 久草免费手机视频 | 国产一区欧美二区 | 中文字幕在线播放视频 | 日韩理论在线播放 | 久久久久久久久久久久久久av | 国产精品美女免费看 | 欧美性做爰猛烈叫床潮 | 一级黄色a视频 | 狠狠久久 | 成人资源网 | 成人a视频在线观看 | 免费成人在线观看视频 | 久久精品国产99国产 | 狠狠做深爱婷婷综合一区 | av综合在线观看 | 国产视频亚洲视频 | 日韩理论在线播放 | 国产99久久久欧美黑人 | 日本在线中文 | 日韩精品一区电影 | 免费中文字幕视频 | 男女激情片在线观看 | 日韩精品一区二区三区电影 | 三级黄色免费片 | 99精品影视 | 摸bbb搡bbb搡bbbb| 五月色婷| 精品欧美一区二区在线观看 | 亚洲色图av | 日日夜夜天天人人 | 91网在线 | 一级黄色av | www色,com | 在线黄网站| 人人草在线观看 | 一级片色播影院 | 在线蜜桃视频 | 成人免费视频网址 | 亚洲欧美国内爽妇网 | av手机版| 国产精品va| 免费三级a| 精品女同一区二区三区在线观看 | 久久久999免费视频 日韩网站在线 | 久久久久久综合 | 91精品久久久久久 | 五月天综合在线 | 日韩xxx视频| 国产美女无遮挡永久免费 | 人人爽人人爽人人片av免 | 手机在线视频福利 | 久久免费国产电影 | 久久伦理| 日韩电影在线看 | 中文字幕在线观看视频免费 | 色狠狠综合 | 国产一区在线视频播放 | 婷婷丁香色 | 免费在线中文字幕 | 国产精品每日更新 | 99精品国产成人一区二区 | 免费在线观看成人av | 精品亚洲欧美一区 | 国产片网站 | 91黄色免费看 | 久久久91精品国产一区二区三区 | 97超碰中文| 久久久久久久久久国产精品 | 国产精品午夜久久久久久99热 | 日本乱码在线 | 欧美在线视频第一页 | 天天操综合 | 国产精品亚洲精品 | 天天摸夜夜添 | 久久精品99久久 | 国产精品一区二区你懂的 | 天天干天天操天天入 | 日本精品久久久久久 | 免费国产一区二区视频 | 国产理论免费 | 欧美成人999 | 久久久 精品 | 亚洲aⅴ久久精品 | 五月婷婷视频 | 精品国产中文字幕 | 婷婷天天色 | 97视频免费播放 | 国产一级不卡视频 | 天天爽夜夜爽精品视频婷婷 | 五月天综合婷婷 | 99久久超碰中文字幕伊人 | 最新色站 | 丁香花在线观看视频在线 | 天天爽天天做 | 成人免费观看a | 97碰在线视频 | 91麻豆精品一区二区三区 | 午夜精品久久久久久久久久久久久久 | 欧美在线视频第一页 | 人人澡人人爽 | 黄色软件视频网站 | www视频在线播放 | 午夜精品一区二区三区在线观看 | 精品欧美在线视频 | 91污视频在线 | 亚洲h在线播放在线观看h | 又黄又爽又刺激的视频 | 久草在线免费新视频 | av在线中文 | 久久久久久久久影视 | 97超碰站 | 黄色小网站在线观看 | 欧美乱大交 | 久久国产精品影视 | 日本精品一区二区在线观看 | 国产精品入口66mio女同 | 992tv人人网tv亚洲精品 | 在线观看日韩国产 | 日本视频精品 | 2019天天干天天色 | 久热精品国产 | 人人爽人人爽人人爽学生一级 | 免费高清国产 | av天天干 | av软件在线观看 | 国产精品九九久久99视频 | 亚洲1区在线 | 亚洲色图av | 久久精品麻豆 | 白丝av在线 | 久草精品视频 | 国产99久| 中文字幕无吗 | www.夜夜骑.com| 久草在线99| 亚洲欧美成人在线 | 亚洲精品欧美视频 | 五月在线视频 | 成人av在线一区二区 | 国产原创中文在线 | 欧美一区二区三区在线看 | 在线播放国产一区二区三区 | 国产精品99久久免费观看 | 欧美a级成人淫片免费看 | 精品国产乱码久久久久久久 | 精品国产诱惑 | 成人禁用看黄a在线 | 精品福利在线 | 日韩av一区在线观看 | 久久精品99国产精品酒店日本 | 亚洲精品国产精品久久99热 | 亚洲最快最全在线视频 | 色狠狠一区二区 | 国产福利在线免费 | 国产精品久久久久久久久久尿 | 中文区中文字幕免费看 | av黄色免费网站 | 国产呻吟在线 | 一区二区不卡视频在线观看 | 香蕉视频最新网址 | 91精品爽啪蜜夜国产在线播放 | www.狠狠色.com | 深爱婷婷 | 激情视频一区 | 国产精品欧美日韩在线观看 | 国产精品黄色av | 美女在线观看av | 在线观看日本韩国电影 | 欧美日韩高清免费 | 国产剧情久久 | 日韩欧美精品一区 | 日韩美女av在线 | 夜夜澡人模人人添人人看 | 人人玩人人添人人 | 国产成人久久av977小说 | 免费看麻豆| 最新国产精品亚洲 | 激情网站五月天 | 亚洲免费观看在线视频 | 国产精品伦一区二区三区视频 | 国产高清精品在线观看 | 久久久精品午夜 | 99热最新 | 我要看黄色一级片 | wwxxxx日本 | 91在线看黄 | 欧美污在线观看 | 亚洲视频axxx | 成人h在线观看 | 国产91丝袜在线播放动漫 | 欧美日韩调教 | 日本午夜在线亚洲.国产 | 国产精品2020| 久久精品国产免费看久久精品 | 操操操夜夜操 | 国产精品18毛片一区二区 | 国产日韩在线一区 | 激情综合亚洲 | 国产精品视频免费观看 | 亚洲丝袜中文 | 免费欧美高清视频 | 在线有码中文 | 久久这里| 亚洲人成免费网站 | 在线免费性生活片 | 成人性生爱a∨ | 制服丝袜在线91 | 午夜a区| avhd高清在线谜片 | 99精品在线观看视频 | 日韩精品久久久久久 | 91在线视频观看 | 久久精品一 | 久久精品首页 | 国产中文在线播放 | 天天av综合网 | 99精品国产兔费观看久久99 | 国产精品九九热 | 国产91免费在线观看 | 国内精品久久久久影院优 | 在线观看亚洲精品视频 | 一区二区三区在线免费观看视频 | 中文字幕丝袜 | 正在播放五月婷婷狠狠干 | 成人h动漫在线看 | 综合色亚洲| 欧美黑吊大战白妞欧美 | av综合网址| 欧美日韩免费一区二区 | 国产精彩在线视频 | 欧美激情视频一二三区 | 精品国产成人av在线免 | 2022中文字幕在线观看 | 亚洲精品视频偷拍 | 91九色老 | 天天艹天天操 | 五月宗合网 | 亚洲视频电影在线 | 特级毛片在线免费观看 | 国产在线观看中文字幕 | 中文在线www | 在线国产视频 | 日韩欧美视频一区 | 国产日韩精品一区二区在线观看播放 | 国产福利免费在线观看 | japanesefreesexvideo高潮| 欧美国产一区二区 | 国产97视频 | 欧美色伊人 | 在线观看中文字幕一区二区 | 国产超碰97 | 久久视频在线观看免费 | 狠狠躁18三区二区一区ai明星 | 国产亚洲精品久久久久久电影 | 久久精品欧美一区 | 久久精品中文视频 | 亚洲免费色 | 欧美在线91 | 六月色婷| 一区二区三区精品在线视频 | 99久久99久久精品免费 | 天天拍天天爽 | 最近中文国产在线视频 | 在线国产能看的 | 中文字幕中文字幕 | 中文字幕一区二区三区在线播放 | 国产一级电影免费观看 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲va天堂va欧美ⅴa在线 | 在线91av | 亚洲精品天天 | 国产伦精品一区二区三区… | 黄色国产在线 | 日韩天堂在线观看 | 久久公开视频 | 在线色吧| 欧美国产不卡 | 伊人日日干 | 国产无套视频 | 中文字幕在线看视频国产 | 国产精品免费观看在线 | 国产在线看一区 | 国产精品久久99综合免费观看尤物 | 欧美性生交大片免网 | 久久久久五月 | 免费日韩电影 | 黄色a一级片| 天天av天天| 99久久er热在这里只有精品15 | 天天操欧美 | 天堂av免费在线 | 精品天堂av | 91精品国产三级a在线观看 | 免费看一级片 | 日韩视频在线观看免费 | 久热久草在线 | 亚洲人成在线观看 | 国产精品久久 | 天天综合色网 | 国产成人一区二区三区 | 狠狠狠狠狠狠干 | 美女久久一区 | 四虎永久免费在线观看 | 久久精品电影院 | 国产午夜精品av一区二区 | 国产日韩精品一区二区在线观看播放 | 97伊人网| 亚洲免费精品一区二区 | 婷婷精品国产欧美精品亚洲人人爽 | 亚洲欧美日韩国产 | 五月婷婷一级片 | 日韩乱理 | 国产麻豆果冻传媒在线观看 | 中文字幕资源网在线观看 | 在线观看中文字幕av | 国产精品视频99 | 国产日韩在线一区 | 色婷婷www| 黄色.com| www.成人久久 | 免费网站黄色 | 一区二区三区手机在线观看 | 最新av网站在线观看 | 色综合久久88色综合天天人守婷 | 中文字幕第一 | 91免费看黄色 | 色在线观看网站 | 国产精品99在线播放 | 开心激情综合网 | 中文国产字幕 | 国产精品麻豆视频 | 97香蕉久久国产在线观看 | 日韩色综合 | 91精品久久久久久久久 | 中文字幕在线观看一区 | 国产精品中文字幕在线观看 | 999免费视频 | 久久a免费视频 | 亚洲传媒在线 | 亚洲二区精品 | 国产一区国产精品 | 能在线观看的日韩av | 日韩精品一区二区免费 | 亚洲免费专区 | 最近日韩免费视频 | 亚洲在线视频播放 | 狠狠狠狠狠狠狠狠干 | 国产麻豆视频免费观看 | 青草视频在线播放 | 久久精品香蕉视频 | 天天草天天 | 欧美日韩不卡一区二区 | 中文字幕在线视频精品 | 中文字幕在线播放视频 | 青青啪 | 日韩欧美xxx| 国产成人三级一区二区在线观看一 | 国产一区影院 | 成人h动漫在线看 | 天天射综合网站 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 欧美午夜久久 | 一级免费观看 | 99日精品 | 亚洲美女在线一区 | 国产高清不卡 | 五月婷婷免费 | 中文字幕在线观看视频网站 | 天天操夜夜看 | 亚洲国产精品一区二区久久hs | 国产精品久久久久久五月尺 | 日韩免费成人 | 国产精品一区二区久久国产 | 伊人久久一区 | 日韩在线观看你懂得 | 亚洲精品资源在线 | 久久久精品网站 | 中文字幕在线播放av | 成人欧美一区二区三区黑人麻豆 | 国产自产高清不卡 | 日日夜夜网站 | 成人av电影在线 | 国产高清视频在线免费观看 | 国产第一页精品 | 久久天堂亚洲 | 国产成人av在线 | 日韩羞羞 | 国产69久久久欧美一级 | 韩日精品视频 | 中文网丁香综合网 | 天天躁日日躁狠狠躁av麻豆 | 欧美日韩网址 | 日韩欧美精选 | 日韩欧美精品一区二区三区经典 | 日本中文字幕电影在线免费观看 | 国产精品成人国产乱一区 | 97超视频在线观看 | 久久久www | 久久美女视频 | 久久精品国产亚洲aⅴ | 国产精品露脸在线 | 中文字幕一区二区三区四区 | 国产一级片一区二区三区 | 亚洲色图激情文学 | 国内久久久久久 | 九九视频在线播放 | 欧美a性 | av成人动漫在线观看 | 精品久久久久久国产91 | 狠狠的干 | 免费在线中文字幕 | 欧美亚洲xxx | 96精品高清视频在线观看软件特色 | 日日夜精品 | 久草免费在线视频 | 97在线观看免费视频 | 国产免费黄色 | 久久久www成人免费毛片麻豆 | 97操操操| 91丨九色丨高潮 | 在线日本看片免费人成视久网 | 日韩av手机在线看 | 日韩午夜大片 | 97久久精品午夜一区二区 | 亚洲va欧美va人人爽 | av电影一区二区三区 | 久久爽久久爽久久av东京爽 | 91探花在线视频 | 久久综合色影院 | 久草在线高清 | 在线电影日韩 | 日韩精品一区二区三区免费观看视频 | 成人网中文字幕 | 美女精品国产 | 亚洲最大av | 97视频成人| 在线观看国产日韩欧美 | 久久国产网站 | 又色又爽又黄高潮的免费视频 | 在线国产一区二区 | 色香蕉网| 美女福利视频网 | 黄色一及电影 | 久久五月情影视 | 中文字幕丝袜美腿 | 中文字幕亚洲不卡 | 免费成人av电影 | 亚洲精品乱码久久久久久蜜桃91 | 一区二精品 | 国产黄色av影视 | 久久久伦理 | 黄网站免费大全入口 | 国产精品美女久久久久久久网站 | 久久tv | 亚洲一区二区视频在线 | 国产日韩精品一区二区三区 | 国模精品一区二区三区 | 日韩av免费在线看 | 久久综合婷婷国产二区高清 | 91成品人影院 | www.超碰 | 亚洲综合激情小说 | 国产馆在线播放 | 婷婷天天色 | 欧美日韩一区二区在线观看 | 亚洲高清在线精品 | 深夜免费小视频 | 91精品久久久久久久久久入口 | 国产黄色大全 | 日韩系列 | 亚洲理论在线 | 黄色a级片在线观看 | 狠狠色丁香久久婷婷综合_中 | 国产女人40精品一区毛片视频 | 欧美污污视频 | 国产无区一区二区三麻豆 | 国产精品免费视频网站 | 91资源在线免费观看 | 国产精品无av码在线观看 | 国产伦精品一区二区三区高清 | www.久久久 | 亚洲精品白浆高清久久久久久 | 久久久久久草 | 国产亚洲亚洲 | 国产精品视频全国免费观看 | 手机av在线免费观看 | av色网站| 玖玖在线观看视频 | 成年人在线免费视频观看 | 五月香视频在线观看 | 最近最新mv字幕免费观看 | 国产精品自产拍在线观看中文 | 黄色免费视频在线观看 | 日韩在线视频免费看 | 成人久久久久久久久久 | 婷婷丁香在线视频 | 久久久精品在线观看 | 国产99黄| 观看免费av| 欧美日本中文字幕 | 国产成人资源 | 精品视频| 欧洲一区二区三区精品 | 国产黄色片在线 | 99久久电影 | 亚洲黄色小说网址 | 成人影片免费 | 日韩精品不卡在线 | 激情欧美日韩一区二区 | 日韩av在线不卡 | 亚洲国产精品一区二区久久,亚洲午夜 | 三上悠亚一区二区在线观看 | 超碰在线人人97 | 女人18片毛片90分钟 | 8x成人免费视频 | 9色在线视频 | 日韩高清免费在线 | 中文字幕乱码一区二区 | 悠悠av资源片 | 欧美日韩高清一区 | 色婷婷www | 日韩在线观看a | 人人爽人人爽人人片 | 99国内精品久久久久久久 | 国产精品成人av电影 | 一区二区三区在线电影 | 国产精品女教师 | 丁香五香天综合情 | 久久国语露脸国产精品电影 | 久久精品视频国产 | 日本精品视频在线观看 | 日韩videos高潮hd | 国产中文字幕久久 | 91正在播放| 亚洲视频 在线观看 | 91精品亚洲影视在线观看 | 一二三区在线 | 国产精品久久久久久妇 | 狠狠干天天色 | 国外成人在线视频网站 | 福利视频入口 | 国产中文视 | av电影一区 | 精品视频资源站 | 日韩成人免费电影 | 国内精品久久久久久久久久 | 国产美女视频一区 | 免费福利片2019潦草影视午夜 | 日韩电影一区二区三区 | 最新午夜电影 | 国产91全国探花系列在线播放 | 国产精品毛片久久久久久久久久99999999 | 成人a在线| 国产成人精品免费在线观看 | 日韩精品一区二区免费视频 | 丁香六月婷婷开心 | 黄视频网站大全 | 欧美伦理一区 | 91精品少妇偷拍99 | 久久嗨 | 96精品高清视频在线观看软件特色 | 九九免费在线观看 | 毛片网在线播放 | 欧美天堂视频在线 | 手机看片久久 | 亚洲日b视频 | 久久精品看片 | 911香蕉视频 | 美女视频黄的免费的 | 免费看的视频 | 中文在线字幕免 | 91看片淫黄大片一级在线观看 | 一区二区欧美日韩 | 国产 在线 高清 精品 | 一级黄色片在线播放 | 欧美一级小视频 | 国产精品免费视频观看 | 黄色一级免费 | 免费视频 三区 | 国产综合小视频 | 欧美精品首页 | 91麻豆精品国产91久久久使用方法 | 国产精久久久久久久 | 成人av电影免费观看 | 在线看的av网站 | 色丁香色婷婷 | 日一日操一操 | 日韩免费成人 | 青青久草在线视频 | 99久久久国产免费 | 91在线中文字幕 | 一区二区电影在线观看 | 国产一级视频免费看 | 日韩av一区二区三区四区 | 国产亚洲综合性久久久影院 | 99在线观看 | 日本中文字幕高清 | 亚洲精品在线网站 | 在线免费av电影 | 日韩高清在线一区二区 | 日韩一区在线播放 | 婷婷亚洲综合 | 国产亚洲精品久久久久久电影 | 久久精品导航 | 日韩免费视频观看 | 国产福利91精品 | 91精品国产综合久久福利不卡 | 欧美性生活久久 | 亚洲精品美女久久久久 | 婷婷久久五月天 | 中文字幕在线观看不卡 | 日本mv大片欧洲mv大片 | 在线a人v观看视频 | 日韩久久久久久久久久久久 | 免费色视频| 91精品久久久久久综合五月天 | 日日夜夜天天人人 | 2022国产精品视频 | 五月天激情视频 | 九九精品毛片 | 欧美午夜a| 亚洲欧美视频一区二区三区 | 日日日操操 | 国产h在线播放 | 99这里精品| 久久99国产精品久久99 | 处女av在线 | 成人免费av电影 | 人人澡澡人人 | 日韩免费中文字幕 | 日韩一二三区不卡 | 中文字幕av最新更新 | 免费成人黄色 | 奇米导航 | 视频直播国产精品 | 欧美日韩国产三级 | 免费毛片aaaaaa | 精品视频999| 在线观看国产v片 | 久久国产高清视频 | 91麻豆精品国产91 | 中文字幕 欧美性 | 视频国产一区二区三区 | 麻豆视频免费网站 | 天天超碰| 特级毛片在线免费观看 | 最新高清无码专区 | 黄色官网在线观看 | 国产一级久久 | 91精品综合| 久久综合久久综合久久综合 | 97看片吧| 久久视频在线看 | 免费观看黄色12片一级视频 | 免费的黄色av | 久久久久久久影视 | 国产女人18毛片水真多18精品 | 免费黄色看片 | 免费看黄的 | 亚洲国产精品久久久久久 | 91视频91自拍| 亚洲精品av中文字幕在线在线 | 欧洲视频一区 | 国内精品久久影院 | 夜夜高潮夜夜爽国产伦精品 | 九九热免费视频在线观看 | 日韩中文久久 | 久久99爱视频 | 成人在线视频你懂的 | 毛片网站免费在线观看 | 日韩欧美视频在线播放 | 亚洲在线成人精品 | 在线观看成人一级片 | 97免费| 91av资源在线 | 日韩欧美一区二区三区黑寡妇 | 亚洲精品在线二区 | 日韩av三区 | 波多野结衣精品 | 亚洲日本黄色 | 又大又硬又黄又爽视频在线观看 | 亚洲精品在线视频观看 | 国产精品久久婷婷六月丁香 | 激情一区二区三区欧美 | avove黑丝| 一区二区三区精品久久久 | 国产综合激情 | 一级性视频 | 天天av资源 | 亚洲精品国产高清 | 亚洲精品国产成人av在线 | 爱射综合| 成人黄色毛片视频 | 国产精品免费看 | 精品久久久久久久久久久院品网 | 久久久久久久久久久国产精品 | 黄色精品一区二区 | 国产福利电影网址 | 国内精品国产三级国产aⅴ久 | 欧美日韩国产成人 | 中文字幕视频一区二区 | 视频一区视频二区在线观看 | 免费在线观看日韩视频 | 三级大片网站 | 国产专区在线视频 | 日韩精品免费一区 | 欧美性脚交 | 欧美片一区二区三区 | 国产午夜不卡 | 免费看的黄色片 | 日韩黄色免费看 | 91黄视频在线 | av电影亚洲| 激情综合网婷婷 | 久久久久久电影 | 午夜av网站| 久久久国产电影 | 亚洲影院一区 | 二区三区毛片 | 日日操操操 | 久操视频在线 | 国产99久久久久 | 黄色91在线 | 久久久影院一区二区三区 | 国产免码va在线观看免费 | 超碰在线观看99 | 久久精品视频在线免费观看 | 久久99精品久久只有精品 | 久久精品中文字幕 | 99久久婷婷国产综合精品 | 久久久久久久久久福利 | 亚洲天堂网站 | 中文字幕电影网 | 中文字幕免费看 | 免费av福利 | 人人揉人人揉人人揉人人揉97 | 亚洲国产欧洲综合997久久, | 蜜桃av人人夜夜澡人人爽 | av免费黄色 | 国产美女视频免费观看的网站 | 182午夜在线观看 | 精品在线免费视频 | 国产色就色 | 国产精品一区二区 91 | 国产美女精品人人做人人爽 | 欧美视频一区二 | 超碰在线97免费 | 亚洲国产精品成人综合 | 成人午夜黄色 | 久国产在线播放 | 亚洲一区精品人人爽人人躁 | 一区二区三区四区精品视频 | 毛片1000部免费看 | 久久综合婷婷国产二区高清 | 娇妻呻吟一区二区三区 | www欧美xxxx | 午夜精品一区二区国产 | 日韩经典一区二区三区 | www.啪啪.com| 成人一级免费电影 | 国产最新在线视频 | 五月婷婷综合激情网 | 久久精品2 | 亚洲成人av在线 | 最新国产在线 | 国产精品女同一区二区三区久久夜 | 九九热久久免费视频 | 国产午夜视频在线观看 | 国产女人40精品一区毛片视频 | 98涩涩国产露脸精品国产网 | 亚洲最新视频在线 | 午夜精品视频一区二区三区在线看 | 久久精品国产免费看久久精品 | 国产精品久久在线 | 婷婷黄色片 | 久草免费福利在线观看 | 97在线视频免费 | 国产中文字幕亚洲 | 高清视频一区二区三区 | 激情婷婷| 91福利区一区二区三区 | h视频日本 | 在线免费视频 你懂得 | 激情在线网址 | 中文字幕二区三区 | 国产资源精品在线观看 | 精品久久久久久久久久久院品网 | 日本中文字幕在线一区 | 国产精品初高中精品久久 | 久久av网址 | 91九色porn在线资源 | 亚洲精品成人av在线 | 免费久久久 | 久久精品视频18 | 欧美一区成人 | 精品在线视频观看 | 青青河边草手机免费 | 亚洲乱码中文字幕综合 | 欧美亚洲国产精品久久高清浪潮 | 久操视频在线免费看 | 国产精品美女在线观看 | 国产高清无av久久 | 国产精品久久久久aaaa九色 | 国产精品久久中文字幕 | av五月婷婷 | 96精品视频 | 中文在线最新版天堂 | 免费国产黄线在线观看视频 | 亚洲在线激情 | 日韩高清一二区 | av7777777| 在线色吧| 国产精品久久久久永久免费 | 久久99深爱久久99精品 | 日韩欧美高清在线 | 国内一级片在线观看 | 国产黄在线观看 | 亚洲五月 | 丁香六月激情婷婷 | 国产成人精品久久亚洲高清不卡 | 欧美午夜剧场 | 天天摸天天舔 | 日日夜夜精品视频天天综合网 | 国产香蕉视频在线播放 | 91麻豆精品国产91久久久更新时间 | 日韩高清激情 | 国产成人精品一区二三区 | 色婷婷丁香 | 午夜av一区二区三区 | 最近2019年日本中文免费字幕 | 91综合视频在线观看 | 园产精品久久久久久久7电影 | 91亚洲精品久久久蜜桃借种 | 国产成人精品一区二区三区免费 | 999抗病毒口服液 | 99久久国产免费看 | 中文字幕久久精品一区 | 丁香花在线观看视频在线 | av成年人电影 | 少妇性aaaaaaaaa视频 | 日日夜夜噜噜噜 | 国产精品视屏 | av亚洲产国偷v产偷v自拍小说 | 成年人在线免费看片 | 久久午夜精品 | 在线精品一区二区 | 午夜国产在线 | 久久久高清 | 香蕉精品视频在线观看 | 午夜精品久久久久久久99无限制 | 五月天,com | 国产精品欧美一区二区 | 欧美a性| 在线观看黄色免费视频 | 天天插日日射 |