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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

制作自己的xmpp/gtalk客户端

發布時間:2023/12/29 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 制作自己的xmpp/gtalk客户端 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文作者的這個研究過程跟我的好像,我也在xmpp和libjingle之間輾轉研究,用了xmppframework,libjingle,gloox,其中libjingle我是以前都研究過,所有基于它的P2P進行數據傳輸這部分沒有問題,也是會遇到用戶系統的問題,我們需要使用自己的用戶系統,又不想建立自己的STUN,而xmppframework這個又實現的不完整而且也沒什么資料,所以最后又使用gloox來實現消息與數據的傳輸。確切的來講使用了先后使用了libjingle和gloox來實現了兩個不同的項目的不同需求。


[轉貼]制作自己的xmpp/gtalk客戶端

1.[轉貼]制作自己的xmpp/gtalk客戶端Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:07

這里有很多xmpp的開源庫

http://xmpp.org/software/libraries.shtml

之前我研究了一下QXmpp,是基于qt的

然后又順帶跑去研究了一下qt

先去qt網站上把sdk下載并安裝好,然后用qt creater打開.pro文件進行編譯

就可以運行里面的example了,這里記住就是安裝路徑和源代碼路徑都不能有中文或者空格

這里能看出qt多么小家子氣

當然了,之前接觸qt是通過python的qt庫,這回仔細看了一下qt的sdk

已經QXmpp對qt的調用,還是感嘆一下qt確實是做的很不錯的

很多東西都封裝的很好,并且最大的優勢是跨平臺,源代碼只需要到對應平臺的sdk上編譯一下就可以使用了,不需要任何修改

---------------------------------------------------------------------------------------

但我還是想用純c++來做,畢竟在qt上寫程序有了通用性缺也得礙手礙腳

所以又找到了gloox 0.9.9.7,這個是純C++的,并且用VS2008編譯很方便,不需要任何修改

建立一個靜態庫項目,把src里的文件拷貝并包含進項目,就可以編譯了,記住不能用定義為UNICODE,否則會出錯

因為gloox使用的是UTF-8編碼,所以只需要將數據轉換成UTF-8再傳給gloox處理就可以了,不需要把整個庫都改成UNICODE

不過現在正在研究怎么用gloox連接到gtalk服務器,看上去沒有OXmpp方便

------------------------------------------------------------

吃完盒飯,回來繼續研究看問題出在哪

研究了一下gloox的源碼,發現有點不太好的地方,Client類會把domain和server搞混

gtalk的domain應該是gmail.com,而server應該是gtalk.google.com

而Client類都用的同一個,所以之前沒法連接,初始化以后再手動改下server地址就可以了

把message_example那個例子里的

JID jid( "hurkhurk@example.net/gloox" );
j = new Client( jid, "hurkhurks" );?

改成下面的代碼就可以了登陸了

j = new Client("username","password","gmail.com","gtalk",5222);
j->setServer("talk.google.com");

然后用其他賬號給這個賬號發個消息,會收到消息回復

2.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:10

做了一個MFC對話框程序把gloox程序包裝了一下



填寫server domain username password等信息就可以登陸到不同的服務器了

現在已經試驗了gtalk和renren網的都沒有問題

右側為好友列表

下面是收到的消息列表 以及文本信息輸入框



大概的思路是,點擊登陸 把用戶輸入的數據獲取過來然后開啟一個線程去啟動gloox的client服務

收到消息以后把MessageSession發送給主界面,當界面點擊發送按鈕的時候調用MessageSession::Send發送消息?

3.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:10

遇到問題了

雖然基本的消息發送接收已經完成了,但是最關鍵的語音部分還是有問題

之前我看google的文檔有點誤解了google的意思,我以為libjingle是一個xmpp的語音插件

所以先去找了gloox庫來實現xmpp相關的內容,等功能完善了再來看libjingle,沒想到libjingle是整個xmpp解決方案

完全就是gtalk的底層

所以把libjingle找出來研究了一番,問題很嚴重,里面采用的語音GISP庫是不開源的,需要另外下載

那就沒法移植到手機上了,但還是抱著學習的態度歷經千辛萬苦到網上把那個庫找過來了

編譯libjingle成功,運行call example,一旦打入或者打出電話程序直接異常終止了

難道GISP已經過期了?

無奈繼續到網上找資料

1、gloox已經準備在下個版本中集成jingle了,但今年10月份才發布了1.0版本,這要什么時候才能等到下個版本啊。。。

2、有個德國人用libjingle+speex語音庫做了一個demo叫myjingle,可惜相關的資源下載地址全部失效了

http://www.bluehands.de/software/beat/myjingle/



實在沒辦法的話自己動手來實現libjingle+speex吧

4.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:11

自己動手編譯libjingle

編譯的過程中有幾點需要注意:

庫有沖突,需要把項目屬性->C/C++->代碼生成->運行庫 改成多線程調試(/MTd)

使用libjingle中example里的xmppthread類進行登錄測試,不成功,直接報Logged out,截包發現除了查了下DNS其他壓根什么都沒法出去

使用pcp那個例子登錄可以成功,里面沒有采用xmppthread類,而是自己的main函數中寫了個類似xmppthread過程

但會把主線程堵死,我想把這個過程放到另外一個線程中而不影響程序的主線程

另外開個線程執行pcp的main,成功

登錄成功

5.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:11

研究了兩天的libjingle

了解了sigslot消息機制,智能指針,多看看這種高手的作品收獲頗多啊

這里是google文檔的一個粗譯文?http://cyclone.blog.ubuntu.org.cn/2008/01/23/libjingle-create-a-program/

大概懂了libjingle的運行機制,自己重新用mfc+libjingle寫客戶端,已經可以監聽好友的上線下線狀態了

但不知道要怎么發消息,例子里面只提供了文件傳輸和語言,真想不通為了不提供一個最基本的文本消息收發的例子

然后找了一整個下午相關的資料,翻遍了libjingle的源碼,也沒找到任何發消息相關的類、方法

難道libjingle連最基本的消息收發都要自己寫?

貌似是的,自己集成一個talk類開始動工吧

自己寫了一個MessageTask類來截獲消息

主要是重寫XmppTask這兩個函數就可以了

bool MessageTask::HandleStanza(const XmlElement * stanza) {
if (stanza->Name() != QN_MESSAGE)
return false;
QueueStanza(stanza);
return true;
}?

int MessageTask::ProcessStart() {
const XmlElement * stanza = NextStanza();
if (stanza == NULL)
return STATE_BLOCKED;
TextMessage msg;?
msg.from_jid = Jid(stanza->Attr(QN_FROM));
const XmlElement * body_element = stanza->FirstNamed(QN_BODY);
if( body_element == NULL)
return STATE_BLOCKED;
msg.body = body_element->BodyText();
SignalRecieveMessage(msg);
return STATE_START;
}

其中TextMessage也是自己寫的一個容器類

發消息的話調用下面就可以了

buzz::XmlElement *message = new buzz::XmlElement(buzz::QN_MESSAGE);
message->AddAttr(buzz::QN_FROM,pump.client()->jid().Str());
message->AddAttr(buzz::QN_TO,status.jid().BareJid().Str());
message->AddAttr(buzz::QN_TYPE,buzz::STR_CHAT);
buzz::XmlElement* bodymsg = new buzz::XmlElement(buzz::QN_BODY);
bodymsg->AddText("I'm here");
message->AddElement(bodymsg);
pump.client()->SendStanza(message);?

真想不通,難道google為了保證文本消息這塊的超強可定制性干脆就不寫了留給別人去寫??

這可是XMPP最基本的功能

6.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:12

libjingle基本消息發送功能已經完成了,正準備開始往手機上移至這部分功能了

結果。。。

我的目的就是想做一個通用的xmpp協議客戶端,不只是gtalk,還有校內等等所有的xmpp協議服務器都能登錄

我測試了一下,發現libjingle除了gtalk服務器,其他一概無法登錄

網上也有說改saslplainmechanism.h文件的方法來支持其他服務器

我試了一下沒用,根本就沒調用到里面的功能就已經中斷了

先是talk.renren.com來回一個stream:stream頭就沒下文了

然后是jabber.org,進行PLAIN驗證的時候出錯了,錯誤內容:SEC_I_INCOMPLETE_CREDENTIALS

發現libjingle里面寫著這么一句// We don't support client authentication in schannel.



昨天和gloox那邊通信過了,他們下個版本中準備支持jingle,但是沒準備支持語音

語音的話還是得自己寫,為了保證客戶端的通用性我只能又回頭用gloox了

繞了一個大圈,回到了原點

7.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:12

重新到網上把最新的gloox1.0下下來

仔細的測試了一下,功能確實很強大,很方便,很易用

我的做法是開個子線程來運行gloox的消息循環,在handle函數中調用sendmessage把內容發給主線程

這里采用sendmessage的原因就是保證線程安全

雖然效率是沒有postmessage高,但至少不會出問題

pc上的測試完善以后就開始動手去移植到wince上了

莫名其妙M8 SDK的time.h里面居然沒有time這個函數

只能自己寫了個mytime.h和mytime.cpp手動寫了time函數加到項目中

接著全部編譯錯誤清了以后來了鏈接錯誤

error LNK2019: 無法解析的外部符號 DnsRecordListFree

等等幾個dns相關的函數全都出問題了

奇怪,到wince6和wince5的sdk目錄下都找了一下,都有windns.h這個文件,但沒有dnsapi.lib這個庫

MSDN上是說在dnsapi.lib里的,難道是wince上收縮到其他庫里面了?幾乎把其他所有的庫都加進去了還是一樣報錯

奇怪了,難道wince只提供了dns相關函數的定義頭文件,沒有lib的實現?



找到原因了,根據readme.wince的說明把config.win里面全部的設置項全部去掉了,其中就有一項HAVE_WINDNS_H是關鍵

去掉以后就編譯成功了,但編譯出來的只有dll沒有lib

對比我新建的動態庫項目和他自帶的庫項目發現時少了DLL_EXPORT這個預處理宏

加上以后再等個幾分鐘編譯,終于成功了

8.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:13

成功把gloox1.0在wince平臺下編譯,這里注意一點gloox動態鏈接庫編譯方式的時候有個bug,會提示gloox.h里面的那些常量 無法解析的外部符號 錯誤

沒找到原因,簡單的做法是在自己的項目里添加gloox.cpp

萬事ok,寫了個簡單的窗口開始進行wince上的登錄測試

問題一大堆

首先,因為wince上編譯的時候把TLS支持給去掉了,不去掉會出錯,而去掉了又沒法登錄gtalk服務器。。。

然后登錄renren的時候,因為后綴不是服務器地址,所以要這樣寫

JID login_jid;
login_jid.setUsername(這里寫校內全名賬號);
login_jid.setServer("talk.renren.com");
login_jid.setResource("xmppforwince");
j = new Client(login_jid,m_sPassWord,m_iPort);
j->setServer("talk.renren.com");?

//?

不支持TLS的問題,是因為wince6不支持兩個函數?

InitializeSecurityContextA?

CertVerifyCertificateChainPolicy?

嘗試了一下用第三方庫去代理系統本身的TLS功能,GUNTLS庫?

但對windows開放支持不是太好,主要是linux平臺的東西,要研究又得浪費很多時間?

所有又把眼光放回著兩個函數身上,因為比較奇怪的是wince6并不是完全沒有這兩個函數?

在頭文件里面都寫著的,但奇怪的是庫文件里面沒有,所以是導致的鏈接錯誤?

我想會不會可能系統本身的dll里已經帶了呢?

于是把wince6內核解包,然后用010Editor工具搜?

果然找到了InitializeSecurityContextA函數在schannel.dll里面?

可是任然沒有CertVerifyCertificateChainPolicy這個函數?

我看了下CertVerifyCertificateChainPolicy這個函數主要是進行證書認證返回一個bool?

就干脆把它注釋掉了,應該影響不會太大?

然后用動態載入dll的方法去使用InitializeSecurityContextA函數?

HINSTANCE hInst;
hInst = LoadLibrary(L"schannel.dll");
typedef SECURITY_STATUS (_stdcall *INITPROC)(PCredHandle phCredential,
PCtxtHandle phContext,?
SEC_CHAR SEC_FAR* pszTargetName,?
ULONG fContextReq,
ULONG Reserved1,?
ULONG TargetDataRep,?
PSecBufferDesc pInput,?
ULONG Reserved2,?
PCtxtHandle phNewContext,?
PSecBufferDesc pOutput,
ULONG SEC_FAR* pfContextAttr,?
PTimeStamp ptsExpiry?
);
INITPROC Initlsc = (INITPROC)GetProcAddress(hInst,L"InitializeSecurityContextA");
ASSERT(Initlsc);
error = Initlsc( (PCtxtHandle)&m_credHandle,
(PCtxtHandle)0,
hname,
request,
0,
SECURITY_NETWORK_DREP,
0,
0,
&m_context,
&obufs,
&return_flags,
NULL );
FreeLibrary(hInst);?

好啦 這下gloox庫終于能在wince6上支持TLS了

9.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:13

由于gloox本身對于服務器地址和域名不同的情況支持不好

比如gtalk就是,服務器地址是talk.google.com而域是gmail.com

所以我準備自己來對gloox進行改造一下

把JID這個類徹底改了一下,就只需要username這個屬性存儲全部用戶名,而廢掉domain屬性

因為單純的修改幾個提交domain的地方會導致身份驗證加密那邊會運算出錯

等等等等改了好多地方,終于完美的支持了gtalk和人人網的登錄了

然后整體程序的框架也出來了

現在主要是3個窗口:登錄、主窗口、聊天

因為gloox的handle機制,就是首先對你關心的事件進行注冊

然后再實現相關的借口,一些handle函數

當發生事件時,比如好友發來消息的時候,gloox就會自動調用messagehandle事件

所以只需要把自己的代碼寫在handle函數里讓gloox線程調用就可以了

我之前的想法是另外寫個類專門做handle的容器,然后再在handle事件發生時用消息的形式通知前臺窗口

后來覺得這樣太麻煩了,所以直接讓窗口類繼承了那些handle接口,直接處理

首先登錄窗口就不需要了,登錄窗口只是收集用戶輸入的登錄數據然后告訴主窗口

主窗口去啟動一個后臺線程運行gloox

本來是準備把消息的處理的messagehandle直接注冊到聊天窗口上去

但后來發現這樣做會導致永遠手不到別人發的第一條消息

原因是注冊太慢,新建聊天窗口的過程太慢,導致消息已經過了,還沒有注冊handle函數

所以改成了全部由主窗口去接受所有人發的消息,用一個容量類裝著,這個容器類里面主要是個map<string,list<msg>>

可以通過用戶的JID去找到所有的聊天記錄

新建聊天窗口的時候直接從map容器里面讀取之前的消息,新收到的消息會有主窗口來處理,如果是當前聊天窗口的,就發送過來,不是就先儲存起來

10.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:13

基于gloox的xmpp for m8初步已經完工了

現在已經可以很方便的添加好友,聊天

下一步是做文件傳輸,但一開始就碰釘子了

gloox1.0里面提供的文件傳輸功能好像是xmpp協議本身的擴展

而gtalk支持的文件傳輸是jingle,雖然jingle也被xmpp作為擴展被接受,但是這是兩個不同的東西

所以貌似gloox現在還無法給gtalk發文件

用psi試驗了一下,確實psi無法和gtalk 人人桌面之前相互發送文件

但是psi自身之前是可以的,這說明不需要服務器的特殊支持,而只是客戶端都同時支持就能夠發現了

所以就算不能讓xmpp for m8和gtalk 人人桌面之前文件傳輸的互通

但至少可以讓都用xmpp for m8登陸的人之前傳輸文件,當然啦,還以讓登陸psi或者其他第三方xmpp客戶端之間發送文件

但國內基本上沒什么人用,所以可以忽略



下面是文件傳輸試驗過程中遇到的一些問題字節處理方便的問題和解決方案

最開始我是使用ofstream進行文件讀寫的,收到數據以后然后用ofstream<<data.c_str()的形式把字節流寫入文件

但問題是傳輸文本文件沒有問題,但傳輸圖片的時候,本來13K的圖片就剩下了4K

后來想明白了,是因為<<這種流寫入的形式碰到0就會停止,而實際上還沒寫完data

所以改成了ofstream.write(data.c_str(),data.length())的形式寫入

文件大小沒有問題了,傳過來以后也是13K,但圖片確依然打不開

我用ultraedit仔細對比了源文件和接受后的文件,發現里面的10前面全被加了一個13

看樣子是ofstream進行了自動的回車符替換了

然后知道是因為需要使用二進制文件讀取的方式才能防止回車符自動被替換打開文件的時候加上這個屬性fstream::binary

但結果依然不行,文本文件傳輸沒有問題,但圖片文件寫入的時候還是會導致編碼莫名其妙被篡改了

難道是因為utf-8和ANSI的問題?但因為我的程序中編碼轉換的模塊沒法轉換中間含有0的字符串

所以只能放棄用ofstream改用

FILE *mStream

fwrite(data.c_str(), data.length(),1, mStream);

fclose(mStream);

這種形式,終于完美的傳輸了文件

-----------------------------------------------------------

上面是接受,下面是發送了

例子里面看上去也挺復雜的

gloox首先得綁定一下自己的IP,然后再gloox的主消息循環里面也寫了一堆代碼

但運行的時候有好幾點要注意的

首先是gtalk的特殊性,會在綁定資源以后改寫你的resouce,比如你要綁定的是"myresource"

而綁定成功后會改寫成myresource0F91240D的形式

這個在gloox中有處理,會自動改寫成服務器返回的resouce

但在例子中就有問題了,這句

f->addStreamHost( j->jid(), "211.103.98.203", 6666 );

在運行的時候jid的resouce還沒有被改寫,這時候就會造成503錯誤

所以我把這句放在了onConnect里面

然后是發送給對方的jid需要是全名的,需要包括資源名在內的,如果只寫了bare,那么會報501錯誤

解決了上面的問題就可以成功發送文件了

11.Re:[轉貼]制作自己的xmpp/gtalk客戶端?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:14

之前一篇文章寫完后,發現只能兩個客戶端在同一網段內才能收發文件

原來bytestream這個協議沒有穿透能力

如果需要跨網跨防火墻進行傳輸文件就必須要文件中轉站(這不是廢話嘛,不然不都用飛鴿去了)

socket5 bytestream 大概的工作原理是這樣

首先進行一些前戲,發送文件方和接受方溝通溝通,協商了好了以后,發送方就會發起一個iq,內容如下?

<iq to='lomiou@jabber.org/proxy.netlab.cz' from=zhuliye@gmail.com/gtalk583984' id='uid:4b32d84e:000072ae' type='set' xmlns='jabber:client'>
<query xmlns='http://jabber.org/protocol/bytestreams' sid='uid:4b32d84e:0000701f' mode='tcp'>
<streamhost jid=zhuliye@gmail.com/gtalk583984' host='10.10.10.113' port='7777'/>
<streamhost jid='proxy.eu.jabber.org' host='91.121.109.155' port='7777'/>
</query></iq>

其中可以有多個streamhost節點,就是告訴接收方有這么些個文件中轉服務器可以使用

首先別忘了把自己的jid 和ip地址寫上去,因為你們可能處于同一網段,就沒必要使用中轉服務器了

然后另外再找一些可用的中轉服務器

這里需要利用server discovery來尋找,具體請參考http://xmpp.org/extensions/xep-0065.html

找到以后把相關信息填上作為一個streamhost節點,多幾個比較好,一個出問題其他的還能頂上



然后接收方收到這個xml流就會對streamhost一一嘗試連接,直到找到一個可以連得通的

然后就會回復下面的內容給發送方
<iq from='bottlerun@jabber.org/proxy.netlab.cz' to='bottlerun@gmail.com/xmppform850286462' xml:lang='en' type='result' id='uid:4b32d84e:000072ae'>
<query xmlns='http://jabber.org/protocol/bytestreams'>
<streamhost-used jid='proxy.eu.jabber.org'/></query></iq>

這里就一個streamhost,就是告訴發送方自己的選擇,然后發送方和接收方就會同時和這個streamhost建立連接,一邊發一邊收了



但使用SOCKS5Bytestream有個細節要注意,不使用中轉直接發的話很正常,但如果用了中轉的話就會出現一個問題

發送方是先把數據發送給中轉服務器,而中轉服務器再發送給接收方的,這里就會形成一個異步

發送方把數據發送完畢以后,按例子中就直接關閉連接了,而這時候接收方確還沒有接受完

但又接受到發送方的斷開連接的通知,因此就會導致傳輸出錯

所以我改成了:發送方發送完畢后不接受,接收方直到接受

而這樣還是會有問題,發送方如果不在發送完畢后斷開連接,就不知道該在什么時候斷開了

因為接收方接受完畢以后,即時關閉連接,發送方也不會受到任何通知(這里我也很奇怪,為什么發送方斷開連接的時候,接收方也會斷開,但接收方斷開的時候發送方沒任何通知)

就會導致發送方一直處于發送中狀態

最后的做法是,在發送方使用send發送數據以后再調用一次recv(1),這樣就可以檢測到接收方是否已經關閉了

12.制作自己的xmpp/gtalk客戶端12之In-Band和Out-of-Band?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:15

今天一直在看xmpp協議相關的擴展協議文件?http://xmpp.org/extensions

想找更多的關于jingle的資料,搞明白了一些事情

之前有點奇怪,jingle可以用來傳輸數據,包括多媒體,文件共享等等

但socket5 bytestream也是實現這個功能,那xmpp協議同時要這兩個擴展干嘛?只是提供更豐富的連接方式嗎?

后來搞明白,socket5 bytestream和jingle是兩個不同的概念

jingle主要的作用是利用ICE和STUN等技術實現點對點的連接的一種解決方案

而連接方式和傳輸內容是分離的,socket5 bytestream就是其中一種tcp的連接方式,另外還有UDP、in-band等方式

而內容也可以是各種數據,文件 多媒體數據等等

理論上不需要任何服務器的額外支持,也不需要像單純的使用socket5 bytestream那樣需要中轉服務器

只需要兩個客戶端都支持jingle,就可以實現點對點傳輸

如果連不上的話也可以利用第三方的stun服務器進行連接



這里又多出一個概念In-Band,可以翻譯成“帶內”,和它對應的是 Out-Of-Band“帶外”

http://xmpp.org/extensions/xep-0047.html

所謂In-Band就是把需要傳輸的數據轉換成字節碼的形式用Xmpp協議的形式比如 iq 或者 message節點發出去

就是用的XMPP協議走的通道傳輸附加數據,所以稱為帶內

而“帶外”就是socket5 bytestream這種形式,先利用xmpp進行協商,然后另外去建立一個socket連接

進行數據傳輸,這種一般是利用第三方的proxy中轉服務器,好處是不占用xmpp服務器的資源

因為大家都用In-Band方式來收發文件的話,會把XMPP服務器拖垮的

所以文檔中寫到

Generally, in-band bytestreams SHOULD be used only as a last resort. SOCKS5 Bytestreams will almost always be preferable.?
A server MAY rate limit a connection, depending on the size and frequency of data packets.?
A server MAY disconnect a connection that sends overly large packets as defined by server policy.?
It is RECOMMENDED to use a 'block-size' of 4096.?


看了一下gloox目錄下有InBandBytestream相關的類,以及一個ibb_excample,一會試試看怎么樣



現在我的程序文件傳輸基本上用socket5 bytestream解決了

接下來是語言了,剛剛和gloox協議庫的開發者交流了一下,下一個版本正在開發中并將支持jingle

但是需要等到明年2月到5月才能發布

看了一下jingle那么多復雜的技術ICE STUN等等

要自己來實現有點不太可能了,而現在正在開發的gloox源碼中雖然已經有了不少jingle相關的類

但聽gloox開發者說目前還沒法用

所以我想先試試看In-Band方式來實現試試傳輸語言數據吧

這樣首先就放棄了和其他客戶端的通用性,當然目前好像也只有gtalk支持jingle吧,

其他的客戶端我看連文件傳輸都沒怎么支持好

比如psi的文件發送居然不支持中轉服務器,同樣的也不支持jingle,照樣發布的好好的

上次看到一篇文章說語言每秒鐘能壓縮到5K就夠了

如果In-Band支持不了那么大流量的話也可以進行一些功能上的縮減

比如把實時的語音換成對講機的形式,按住鍵說一句話,對方等傳完的聽完了再按住鍵回復一句話這樣子

當然啦,如果In-Band實在沒法支持也可以利用傳輸文件用的那些個服務器來進行數據中轉

根據今天和別人手機對發消息的經驗來看,速度還是不錯的,GPRS本身速度也是個限制

但問題是延遲比較大,所以還是實時性會比較差



如果網絡方面的問題都解決了,接下來就是要去解決語言的采集、壓縮和播放了

13.NAT穿越原理——STUN?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:16

NAT穿越原理——STUN
知道了jingle是采用STUN技術來實現點對點的連接,因此到網上把STUN相關的資料找了過來?

轉自:http://www.yuanma.org/data/2007/0323/article_2446.htm?

STUN是RFC3489規定的一種NAT穿透方式,它采用輔助的方法探測NAT的IP和端口。毫無疑問的,它對穿越早期的NAT起了巨大的作用,并且還將繼續在ANT穿透中占有一席之地。?

STUN的探測過程需要有一個公網IP的STUN server,在NAT后面的UAC必須和此server配合,互相之間發送若干個UDP數據包。UDP包中包含有UAC需要了解的信息,比如NAT外網 IP,PORT等等。UAC通過是否得到這個UDP包和包中的數據判斷自己的NAT類型。?

假設有如下UAC(B),NAT(A),SERVER(C),UAC的IP為IPB,NAT的IP為 IPA ,SERVER的 IP為IPC1 、IPC2。請注意,服務器C有兩個IP,后面你會理解為什么需要兩個IP。?

(1)NAT的探測過程:(吃個芒果先,呵呵,老媽給的)?

STEP1:B向C的IP1的pot1端口發送一個UDP 包。C收到這個包后,會把它收到包的源IP和port寫到UDP包中,然后把此包通過IP1和port1發還給B。這個IP和port也就是NAT的外網 IP和port(如果你不理解,那么請你去看我的BLOG里面的NAT的原理和分類),也就是說你在STEP1中就得到了NAT的外網IP。?

熟悉NAT工作原理的朋友可以知道,C返回給B的這個UDP包B一定收到(如果你不知道,去讀下我的其它文章)。如果在你的應用中,向一個STUN服務器發送數據包后,你沒有收到STUN的任何回應包,那只有兩種可能:1、STUN服務器不存在,或者你弄錯了port。2、你的NAT拒絕一切UDP包從外部向內部通過(我們公司的NAT就是)。?

當B收到此UDP后,把此UDP中的IP和自己的IP做比較,如果是一樣的,就說明自己是在公網,下步NAT將去探測防火墻類型,我不想多說。如果不一樣,說明有NAT的存在,系統進行STEP2的操作。?

STEP2:B向C的IP1發送一個UDP包,請求C通過另外一個IP2和PORT(不同與SETP1的IP1)向B返回一個UDP數據包(現在知道為什么C要有兩個IP了吧,雖然還不理解為什么,呵呵)。?

我們來分析一下,如果B收到了這個數據包,那說明什么?說明NAT來著不拒,不對數據包進行任何過濾,這也就是STUN標準中的full cone NAT。遺憾的是,full cone nat太少了,這也意味著你能收到這個數據包的可能性不大。如果沒收到,那么系統進行STEP3的操作。?

STEP3:B向C的IP2的port2發送一個數據包,C收到數據包后,把它收到包的源IP和port寫到UDP包中,然后通過自己的IP2和port2把此包發還給B。?

和step1一樣,B肯定能收到這個回應UDP包。此包中的port是我們最關心的數據,下面我們來分析:?

如果這個port和step1中的port一樣,那么可以肯定這個NAT是個CONE NAT,否則是對稱NAT。道理很簡單:根據對稱NAT的規則,當目的地址的IP和port有任何一個改變,那么NAT都會重新分配一個port使用,而在step3中,和step1對應,我們改變了IP和port。因此,如果是對稱NAT,那這兩個port肯定是不同的。?

如果在你的應用中,到此步的時候PORT是不同的,恭喜你,你的STUN已經死了。如果不同,那么只剩下了restrict cone 和port restrict cone。系統用step4探測是是那一種。?

STEP4:B向C的IP2的一個端口PD發送一個數據請求包,要求C用IP2和不同于PD的port返回一個數據包給B。?

我們來分析結果:如果B收到了,那也就意味著只要IP相同,即使port不同,NAT也允許UDP包通過。顯然這是restrict cone NAT。如果沒收到,沒別的好說,port restrict NAT.?

(2)SIP怎么使用STUN?

個人認為這是個很不值得提的問題,不過有許多人問我,還是簡要提一下。其實這是個很簡單的問題,SIP通過STUN得到NAT的外網IP和SIP的信令監聽端口的外網port,替換SIP注冊包中的contact頭中的IP和port,然后注冊。這樣就可以確保當有人呼叫你的的時候注冊服務器能找到你。需要提醒你的是,NAT發現一個連接超過一段時間后沒有活動,它就會關閉這個影射,因此你必須間隔一端時間發送一個數據包出去以keep alive。?

另外,當你要和別人建立RTP通訊的時候,不要忘記把你的SDP中的IP和PORT改成公網IP和PORT。?

也許文章到這里就可以完了,不過很遺憾,顯然我們還有工作沒有完成,那就是對稱NAT。在我后面的文章中,我會對對稱NAT對一些探討,希望你關注我的BLOG,謝謝。

14.制作自己的xmpp/gtalk客戶端13之語言壓縮——牛X的speex?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:16

要實現voip需要解決的幾個問題

語言的采集、壓縮編碼、傳輸、解碼、播放

前面已經討論過了傳輸可以先嘗試用In-Band或者類似文件中轉的方式試試,暫時不考慮比較難實現的jingle

昨天也運行了一下In-Band的例子,用gtalk的服務器也能傳輸數據,每個包大概限制在4K的樣子

而奇怪的psi不支持這種傳輸方式,自己用兩個客服端互相發沒問題

暫時先用In-Band作為語言傳輸方式試試吧,因為簡單,不需要第三方支持,也不需要穿透NAT之類的

但大規模應用的肯定要把google的服務器給拖垮了吧

所以只是作為一個目前試驗階段的載體



之前在研究libjingle的時候層找到了Myjingle的源碼,是德國人寫的一個MFC對jingle的簡單封裝

說是簡單。。。其實很復雜,我看了老半天也沒怎么看懂,語音那塊太復雜了

但里面有一點非常不錯,就是替換掉了libjingle本身用的GISP收費語音庫,而是用了免費的speex庫

今天又把speex庫拿出來研究了一番

充分體會到了什么叫神奇啊

我先用windows自帶的錄音機分別錄了一段說話和一段唱歌,兩個文件都是10秒鐘,大小都是450多K左右,325kpbs

然后用speex嘗試不同的壓縮率

采用默認的壓縮編碼方式,8kHz 質量 8 ,壓縮完以后是50K左右,然后解碼后播放

不管是說話還是唱歌,都非常清晰,完全聽不出有任何任何壓縮的痕跡

然后換成16kHz 質量8,壓縮完以后是27K的樣子(不要問我16kHz為什么壓縮后比8kHz要小,我也沒明白),解碼后播放

依然都很清晰

再換成32kHz 質量2,壓縮后只有8K多(天哪!真小),解碼后播放

會有雜音,但是聲音本身基本沒什么很大的變化,在每個字收尾的時候特別是唱歌時候拖同一個音比較長的時候會有點噪音(怪不得說speex不適合壓縮歌曲,而只適合壓縮說話內容),但依然還是算很清晰的,完全是可以接受的范圍

至少比手機打電話時候的音質要好

最后換成32kHz 質量0,壓縮后只有5K,解碼后播放

這里就很明顯的聽得出來壓縮的痕跡了,雜音很重,聲音也很多走樣了,雖然還是能明白說話的內容,但體驗太差了,放棄



而另外有個屬性bitrate沒太理解,感覺調了對大小和音質都影響不大

根據上面的結果,采用32kHz 質量2來壓縮,完全夠voip使用了

這里來計算一下,10秒的聲音數據,被壓縮到8K,也就是說每秒只有1K不到

之前有聽說比較成熟的GSM,也就是現在我們的手機傳輸量就是1K/S左右

語言數據數據是1K,再加上一些傳輸協議的消耗,怎么也就是1K多點

現在手機的GPRS速度,幾K還是很輕松能達到的,我用的E網,更是經常能達到20K速度,最快的時候甚至能突破30

所以基于2G手機的GPRS來實現VOIP,傳輸速度絕對不會算是個瓶頸

主要還是高延遲,體驗方面可能會比較差



下面要做的是自己寫程序來實現編碼,之前測試是用speex提供的程序

然后把speex移植到wince上,好像speex本身就是跨平臺產品

(本來就是把一堆0101運算成另一堆0101的程序,沒涉及到任何和系統有關的東西,當然很容易跨平臺啦)

還有就是語言采集和播放,到網上找了一個源碼利用waveInAddBuffer相關的函數,還挺好用的

而且在手機上也運行成功了

那么多人罵微軟,卻都看不到微軟的優點啊,pc上的程序,幾乎只要進行很少的修改,甚至不用修改,就可以直接用wince的sdk編譯通過

這才是大公司大手筆啊,通用性這么高,大大減少了開發者的時間,而且文檔,函數都是通用的,學習也很方便

15.基于XMPP協議的網絡游戲開發?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:17

今天突然就想到的點子

之前看到google app engine已經提供xmpp協議的支持的了,我想了好久也沒想到可以用這個干嗎

服務器上隨時開著一個gtalk賬號,客戶端發送消息過去,服務器進行一些處理然后再可以回復一些消息

就這樣可以干嘛呢,一些服務提供?輸出一個列表,告訴客戶端輸入1可以看什么,輸入2可以干嘛,輸入m返回主界面?

客戶端通過向某個服務器上開著的好友發送消息來更新自己的微博?

總舉得這些個功能有點雞肋

但前端時間看到說google wave也是基于xmpp協議的,只不過不像gtalk,xmpp協議只是作為底層,用于當做消息的載體

而更高一層另外還有協議

所以我突然想到能不能我也來把xmpp協議作為一個載體,另外去開發一層更高層的協議實現游戲通信呢

大概原理是這樣

用戶采用gtalk賬號登陸游戲客戶端(因為現在gae只支持gtalk賬號)

登陸成功后列出房間列表,用戶選擇房間1,則自動加“room1@gmail.com”為好友

room1@gmail.com收到用戶添加好友的消息,就知道有用戶進房間了

room1@gmail.com就把當前房間所有的游戲桌信息通過xmpp消息的形式發送給用戶(用戶是幾個幾個在一個桌子上玩的)

并且還可以發送一些其他消息,比如所有在線的好友列表(既當前房間的在線玩家),發送給該用戶

客戶端把收到的該房間所有的游戲桌狀態列表給用戶看,用戶選擇一個游戲桌選擇進入,客戶端發送一條消息告訴room1@gmail.com用戶選擇的房間

room1@gmail.com就把用戶選擇的游戲桌上所有的玩家列表發送給用戶

當所有的玩家都把準備完畢的消息告訴room1@gmail.com以后,room1@gmail.com就會給每個人發送一條消息告訴大家游戲開始

到這里為止,服務器的任務就OK了,一直到游戲結束前,服務器都不需要再和這個游戲桌上的用戶交互

玩家之間自己相互發送消息就可以了

比如飛行棋,玩家1擲骰子點數是3,然后就分別發3條消息給3個對手,告訴對方自己的點數

并且把選擇走的棋子發消息告訴3個對手,只需要這6條消息,就完成了一個玩家的操作過程

然后其他幾個玩家的客戶端根據收到的消息來繪制界面就行了

游戲結束后,玩家發一條消息告訴room1@gmail.com已經結束游戲,room1@gmail.com再把最新的房間內游戲桌信息發送給客戶就行了



這里的優點很明顯:

用戶和服務器端的交互很少,服務器只負責幫用戶找到玩家,接下來只需要玩家之間相互通信就可以了

大大減少了服務器的負擔(當然沒有減輕gtalk服務器的負擔,不過gtalk應該還是能抗住的)

成本很簡單,初期運營的時候google app engine免費的服務器會非常方便,當然gtalk也是免費的



缺點也很明顯:

對游戲有要求,只能是那種對實時性要求不高的游戲,比如飛行棋,撲克牌,象棋,五子棋等等

因為xmpp傳輸需要消耗的時間還是挺長的



還有個問題就是room1@gmail.com的好友是有上限的,所以我想到的做法是用戶加入房間既加為好友,用戶退出房間既刪除好友

這樣保持所有好友都是在線的,好友上限正好是房間上限,一個房間幾百個人還是夠了的

但不知道這么頻繁的增刪好友會不會被gtalk給盯上啊

16.制作自己的xmpp/gtalk客戶端14之語言的采集和編碼?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:17

一直嘗試著自己去手動寫speex的編碼和解碼

因為我覺得沒有必要搞跟speex自帶的編碼解碼程序那么復雜

這里我使用的是speex1.0.5的源碼版本

首先把libspeex項目用vs2008直接打開編譯一下就可以了,如果要編譯那兩個編碼解碼的項目需要下載ogg庫,是一種文件格式庫

拿到所有的頭文件和lib文件拷貝到程序目錄下面

用windows錄音機錄一個幾秒鐘的語言文件

然后編寫語言編碼代碼如下

FILE *fin,*fout;
short in[MAX_FRAME_SIZE];
float input[MAX_FRAME_SIZE];
char cbits[MAX_FRAME_SIZE];
int nbBytes;
void *state;
SpeexBits bits;
state = speex_encoder_init(&speex_nb_mode);//設置壓縮模式
int quality=8;
int frame_size;
speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE,&frame_size );//這個值獲取到一般都是160
speex_encoder_ctl(state, SPEEX_SET_QUALITY, &quality);//設置壓縮質量
fin = fopen("hello.wav", "rb");//打開語言文件
fout = fopen("encode.speex","wb");//創建要輸出的編碼文件
int format,rate,channels,size;
char file_type[12];
fread(file_type, 1, 12, fin);//把wav文件頭12個字節讀出來
read_wav_header(fin,&rate,&channels,&format,&size);//分析wav頭文件,獲取相關的信息,默認rate是22050,channels是1,format是16
speex_bits_init(&bits);
while (1)
{
fread(in, sizeof(short), frame_size, fin);//讀取一段出來
if (feof(fin))
break;
speex_bits_reset(&bits);//初始化SpeexBits?
speex_encode_int(state, in, &bits);//最關鍵的一句,進行編碼,輸出到bits
nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_SIZE);//把bits拷貝到cbits數組
fwrite(&nbBytes, sizeof(int), 1, fout);//將把該段編碼后的大小寫入文件,按我這種配置編碼后是38
fwrite(cbits, 1, nbBytes, fout);//將編碼后的該段內容寫入文件
}
speex_encoder_destroy(state);//清理
speex_bits_destroy(&bits);
fclose(fin);
fclose(fout);?

下面是解碼代碼,跟上面一樣的就不多說了

FILE *fin,*fout;
float output_frame[MAX_FRAME_SIZE];
char cbits[MAX_FRAME_SIZE];
short char_out[MAX_FRAME_SIZE];
void *dec_state;
SpeexBits bits;
speex_bits_init(&bits);
dec_state = speex_decoder_init(&speex_nb_mode);
int quality=8;
int frame_size;
speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE,&frame_size );
speex_decoder_ctl(dec_state, SPEEX_SET_QUALITY, &quality);
fin = fopen("encode.speex", "rb");
fout = fopen("decode.wav","wb");
int format,rate,channels,size;
format = 16;
channels = 1;
rate = 22050;
size = 0;
write_wav_header(fout, rate, channels, format, size);//寫入文件頭
speex_bits_init(&bits);
while (1)
{
int this_frame_size;
fread(&this_frame_size, sizeof(int), 1, fin);//讀取該段大小
fread(cbits, 1, this_frame_size, fin);//讀取編碼
if (feof(fin))
break;
speex_bits_read_from(&bits, cbits, this_frame_size);//將編碼內容寫入bits
speex_decode_int(dec_state, &bits, char_out);//解碼
fwrite(char_out, sizeof(short), frame_size, fout);
}
speex_bits_destroy(&bits);
speex_decoder_destroy(dec_state);
fclose(fin);
fclose(fout);

這里是把事先錄好的聲音文件轉碼,然后再把轉碼文件解碼

接下來要做的就是做成實時錄音轉碼,然后再試試解碼并播放了

錄音要用到waveInAddBuffer和相關的函數,功能是把音頻數據輸出到指定內存塊

而播放要用到waveOutWrite相關的函數,功能是把內存中的音頻數據發送給聲卡進行播放

用這兩個函數的時候一定要用緩存技術,我的做法是建立10個WAVEHDR結構

初始化的時候先把這10個結構都填上數據,然后再不斷的循環去讀取音頻數據

for(;;){
while (pWaveHdr[nhdr]->dwFlags & WHDR_DONE){
printf("do some output: %d!\n", nhdr);
int offset, writed=0;
int length = pWaveHdr[nhdr]->dwBytesRecorded;
for (offset = 0; writed >= 0 && offset < length; offset += writed){
writed = fwrite(pWaveHdr[nhdr]->lpData+offset, 1, length-offset, fp);
printf("write: %d\n", writed);
}
error = waveInAddBuffer(hWaveIn, pWaveHdr[nhdr], sizeof(WAVEHDR));?
if (error != MMSYSERR_NOERROR){
printf("waveInAddBuffer error\n");
return -1;
}
nhdr = (nhdr+1)%HDRCOUNT;
}
}

這里就利用pWaveHdr[nhdr]->dwFlags這個標志,因為waveInAddBuffer和waveOutWrite都是異步的

就靠判斷pWaveHdr[nhdr]->dwFlags是不是等于WHDR_DONE來得知是否執行完畢

播放聲音也是一樣,先在初始化的時候先調用waveOutPrepareHeader再把dwFlags 標志全置為WHDR_DONE,

for(;;){
while (pWaveHdr[nhdr]->dwFlags & WHDR_DONE){
printf("do some output: %d!\n", nhdr);?
if(feof(fp))
break;
error = waveOutWrite(waveout, pWaveHdr[nhdr], sizeof(WAVEHDR));
if (error != MMSYSERR_NOERROR){
printf("waveOutWrite \n");
return -1;
}
int size = fread(pWaveHdr[nhdr]->lpData,1,frame_size,fp);
pWaveHdr[nhdr]->dwBufferLength =size;
nhdr = (nhdr+1)%HDRCOUNT;
}
}

17.制作自己的xmpp/gtalk客戶端15之語音功能移植到wince上?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:18

PC上將語音采集、編碼、解碼、播放功能全做好以后開始往wince平臺移植了

移植的過程困難重重啊

首先就是采集,我之前有一篇文章還夸微軟大公司,產品通用性好呢

結果奇怪的是,我前一天把語音采集用到的相關wavein的那段代碼在wince上運行還好好的,錄音完美

但第二天怎么試都不行了,只錄下來了雪花聲,根本沒錄下來

試了很多方法,網上也找了很多源碼,但就是怎么都不行,嘗試了各種方法整整一天

最后沒辦法了想用directsound試試,不過后來又想起來M8的SDK里面有提供錄音機相關的COM接口IRecord

可以錄音,但可定制性太差了,那個接口就是會自動把錄音結果保存到一個固定目錄下生成一個文件

不過還好中途讀取的聲音會以消息的形式發送給windows,我拿到消息進行編碼就可以了

而他自動生成的錄音文件我只能在每次聊完以后刪掉了



采集終于算是解決了,然后編碼的時候碰到一個另一個大麻煩

手機的CPU浮點運算能力太差了,在PC上,對400多K 10秒鐘的一個WAV文件用8的質量進行編碼大概是700毫秒,0質量是180毫秒

而直接移植到手機上同樣的文件進行編碼,8質量需要130秒(2分鐘多),0質量需要40多秒

天哪!10秒鐘的語音數據需要130秒來編碼,這還得了,離實際需求差遠了

說明speex里面基本上都是浮點運算

無奈只能到網上找資料,看有沒有辦法能提速,而且不只是提一點點速度,也看到有不少人說到這個問題

最后在speex官方網站上終于找到了解決方法,我之前用的是1.0.5版的speex

而1.2beta3版中加入了禁用浮點相關API的設置,我真慶幸我是在不是在1.0.5版發布之后1.2版發布之前來開發這個軟件的

(有這個感嘆是因為gloox,我現在是在1.0版之后和1.1版之前發布這個軟件的,而gloox要1.1版才能支持jingle,所以在那之前我只能自己想把法解決語言傳輸問題)

把最新的1.2rc1版源碼下載下來,在宏定義里面加上DISABLE_FLOAT_API和DISABLE_VBR禁用掉浮點運算

用WM5的SDK編譯以后再重新編譯了一下測試用的程序

速度果然是突飛猛進啊,采用speex_uwb_mode質量8編碼同一個文件是2秒,0質量只需要900毫秒

基本上能滿足要求了



接下來編寫了一大堆代碼,終于可以實現電腦上說話手機上接受了,并且GPRS也沒問題,說明帶寬完全夠了

但現在因為使用的國外的中轉服務器進行收發,速度慢到無法想象。。。

測試了一下,大概延時在20S都30S之間,也就是說你說句話,對方20秒后能接受

然后又試了試In-Band方式,延時大概10S左右

但至少有點GPRS和普通網絡的延時幾乎一樣,說明帶寬已經完全不算個問題了

但由于禁用掉了浮點運算,音質要比PC上壓縮的差,雜音比較多

但能聽清楚對方說什么,可能還要試試看speex的雜音消除功能

18.制作自己的xmpp/gtalk客戶端16之gloox雙向socket5proxy數據傳輸?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:18

本來是打算另外建立一個窗口,建立一個新的SIProfileFT單獨對語言的數據進行管理

結果發現gloox對多個SIProfileFT支持不太好,因此暫時還是把語言傳輸的功能結合到文件傳輸當中

通過文件類型這一個屬性來區分是語音還是文件,自己瞎編了一個類型叫binary/speex-voice-stream

另外解碼和編碼還是非常耗時的,為了不對主線程影響,單獨建立了一個線程用來解碼編碼和播放



因為采用類似文件傳輸的功能來發送語言,因此我最開始的想法是建立兩個連接一個用來收,一個用來發

后來發現自己很傻,這不是socket連接嘛,本來就支持雙向,一個連接就夠了

然后昨天pc上寫了個收發測試程序,果然成功了,雙方既能發又能收

結果今天把wince上接受語言的功能做的差不多,準備做發送的時候,不管怎么發數據,另一方就是收不到

用單步跟蹤進去,發現對方其實是收到了數據的,只不過因為對方是連接發起者,所以ConnectionSOCKS5Proxy的狀態m_s5state一直處于S5StateDisconnected

然后就把收到的數據給丟棄了,所以就導致了發起方只能發送數據,而不能接收數據

可以理解,因為這個類本來就是給文件傳輸做的,而文件傳輸的發起方是不需要接受數據的

但奇怪的是,昨天我是怎么試驗成功了,我把源碼盡量改回昨天的樣子,但還是不行,真見鬼了

看樣子以后還是多做手記,把當時詳細的過程寫清楚

不然老碰到這樣的問題,上次在wince上錄音就是,第一次錄音成功后以后再也沒成功過

沒辦法只能自己手動試試看來改改gloox的源碼

找到connectionsocks5proxy.cpp里面的ConnectionSOCKS5Proxy::handleReceivedData方法

這里有個switch判斷狀態,并且沒有對S5StateDisconnected的處理

所以自己手動在switch的最后面加上

case S5StateDisconnected:
m_handler->handleReceivedData( this, data );?

應該沒什么影響



接下來再解決了一些語言編碼方面的問題后,基本的語音通話功能就算完成了

把軟件發給群上面一些人幫忙測試了,完全沒有問題

GPRS也很流暢,除了延遲會比較夸張以外

19.制作自己的xmpp/gtalk客戶端17之語音延遲問題?[Re: netboy]Copy to clipboard
Posted by:?netboy
Posted on:?2010-04-26 10:19

這里說的語音延遲問題不是網絡延遲,那個取決于網絡狀況,基本上是固定的,除非換個傳輸方法

這里說的語音延遲問題造成的原因是這樣:

A發送說了十秒鐘的話,網絡延遲是3秒

那么正常情況B會在3秒后開始聽到這句話,并在13秒的時候聽完

但如果這時候在第8秒的時候,B的網絡卡了1秒(這種情況出現很正常)

那么A說的后面5秒的內容,B會在9~14秒聽到

那么這里問題就出來了,如果多卡幾次,B聽到的內容延遲就會越來越大,緩沖區里面的數據也會越來越多

但是后面收到的數據又必須等到之前收到的數據被播放完以后再播放

所以結果就是延遲會越來越長

那么解決這個問題有下面這些辦法

1、因為我現在的這款軟件本來就是采用中轉式的傳輸,本來就延遲很慢,很難滿足正常通話要求,干脆換成對講機的形式,就不會有這種情況出現了,按住一個鍵說話,松開話就被發送出去了,這樣本來就是異步的

JS:我還是覺得對講機不太友好,爭取努力解決延遲問題,實在不行的話作為最后的選擇吧

2、丟棄掉那些延遲的包,就比如說剛才的問題,B在9秒同時收到了A在5秒和6秒說的內容,這時候直接把5秒的包丟了,播放6秒的內容,用這種方法來趕上對方的說話速度

JS:這種方法固然能解決延遲越來越長的問題,但問題是某些內容被丟棄了,用戶體驗會很差,老是莫名其妙少了一句話,會讓人抓狂的

3、如果積累了很多過多的包,則不播放那些沒聲音的包。這個方法就是利用人說話的空隙時間,接收方收到了過多的包,則說明出現了網絡延遲的問題,這時候去分析包,如果沒有聲音,就干脆不播放直接丟棄,去播放后面的包,以此來趕上說話放的速度。

上面的方法中我最終選擇了第三種,因為首先不會影響用戶體驗,只丟棄那些沒聲音的包來空出時間,利用對方不說話那段時間把速度趕上來

誰會無止境的說上幾個小時呢是吧

但也有弊端,就是背景太過嘈雜的話,就不好分辨了,無法得知對方對方是不是在說話,但這個問題暫時不考慮吧

最開始我是想去把包解碼然后分析wave數據,求這個包的平均值,如果平均值低于某個零界則認為是無聲包,丟棄

要做到這個功能其實還挺簡單的,因為wave數據還是很好看懂的

不過后來找到了更好的辦法,那就是speex本身提供的 靜音檢測VAD 這個選項來做

靜音檢測(VAD)將檢測被編碼的音頻數據是語音還是靜音或背景噪聲。這個特性在用變比特率(VBR)進行編碼是總是開啟的,所以選項設置只對非變比特率(VBR)起作用。在這種情況下,Speex檢測非語音周期并對用足夠的比特數重新生成的背景噪聲進行編碼。這個叫“舒適噪聲生成(CNG)”。

int dtx = 1;
speex_encoder_ctl(state, SPEEX_SET_VAD, &dtx);

我跟蹤看了一下,不開啟這個選項的時候,每個包都是固定大小,如果開啟的話,有的包會是15字節,有的則只有2字節

所以我想當積累的過多的包時,直接丟棄掉只有2字節的包,當然現在還是在理論階段,能不能成功還得試驗

另外還有兩個與此相關的功能 變比特率(VBR)和 非連續傳輸(DTX)

變比特率是比較重要的功能,默認情況下speex壓縮后每個包大小都是固定的,如果采用了變比特率那么會根據每個段內實際的語音內容而壓縮出不同長度的內容

非連續性傳輸(DTX)是靜音檢測(VAD)/變比特率(VBR)操作的額外選項,它能夠在背景噪聲固定時,完全的停止傳輸。如果是基于文件的操作,由于我們不能停止對文件的寫入,會有5個比特被用到這種幀內(相對于250bps)。

如果這三個選項開啟,能夠極大的減少編碼后的數據長度,我測試了一下,大概減少了一倍左右

不過可惜,因為wince上因為性能原因我把浮點運算禁用掉了,而變比特率完全是基于浮點運算的,因此也得禁用掉

不過只開啟靜音檢測和非連續性傳輸的話也能一定量的減少傳輸量



pc上測試沒有問題后我就去看wince平臺上表現怎么樣了

結果發現根本就完全沒反應,加了VAD和DTX特性后和沒加效果一樣

后來想起來因為M8上的浮點運算能力有限,所以禁用掉了浮點運算,而VBR是基于浮點運算的,因此得一起禁用

而在到網上找了下資料發現VAD和DTX都是基于VBR的

這下難道又進死胡同啦,難道wince平臺上就沒法使用VAD特性?

我重新把speex說明書上面關于CPU性能優化那段拿了出來好好看了一下

The single that will affect the CPU usage of Speex the most is whether it is compiled for floating point or fixed-point. If your
CPU/DSP does not have a floating-point unit FPU, then compiling as fixed-point will be orders of magnitudes faster. If there
is an FPU present, then it is important to test which version is faster. On the x86 architecture, floating-point is generally
faster, but not always. To compile Speex as fixed-point, you need to pass –fixed-point to the configure script or define the
FIXED_POINT macro for the compiler. As of 1.2beta3, it is now possible to disable the floating-point compatibility API,
which means that your code can link without a float emulation library. To do that configure with –disable-float-api or define
the DISABLE_FLOAT_API macro. Until the VBR feature is ported to fixed-point, you will also need to configure with
–disable-vbr or define DISABLE_VBR.?

這才想起來好像當時在編譯speex1.2rc1版時確實看到一個宏定義叫fixed-point,當時也沒在意

說不定以M8上這么強大的CPU運行定點數也完全夠呢

于是把DISABLE_FLOAT_API和DISABLE_VBR特性刪掉以后再次編譯了一遍libspeex

然后再次運行wince上的程序,發現速度很快,幾乎和禁用掉浮點運算速度差不多

而且因為有了VBR的特性,VAD和DTX都運行得很好

我拿了一個826k 19秒的一個wav文件做測試,因為為了測試靜音檢測功能,所以19秒中只稍微講了幾句話,其他都是沒有聲音

統一都采用了speex_uwb_mode的壓縮方式

平臺 speex版本 不開啟任何特性 不開啟任何特性 開啟VAD和DTX 開啟VAD和DTX 開啟VAD和DTX和VBR 開啟VAD和DTX和VBR?
質量8 質量2 質量8 質量2 質量8 質量2?
PC 1.0.5 50K 17K 32K 12K 24K 24K?
WINCE 1.2rc1 40K 16K 19K 8K 16K 16k?



這里測試結果可以看出,不管是高質量還是低質量,VAD和DTX這兩個屬性都可以減少壓縮后的數據量

而VBR這個屬性在高品種的時候可以減少數據量,但低品質的時候反而增加了數據量

而且在wince上加入了VBR以后運行速度明顯要慢一兩秒

最后再汗一個800K壓縮到8K,壓縮了100倍,而解壓后仍然很清晰,技術的力量真強大啊

總結

以上是生活随笔為你收集整理的制作自己的xmpp/gtalk客户端的全部內容,希望文章能夠幫你解決所遇到的問題。

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

久久免费看片 | 黄色在线观看www | www.久久99| 波多野结衣电影一区二区 | 国产亚洲精品美女 | 99久久精品午夜一区二区小说 | 亚洲女裸体 | 色小说av| 97综合在线| 91视频啊啊啊 | 国产精品网红福利 | 中文字幕免费观看视频 | 国产精品一区二区三区观看 | 一区二区精品在线观看 | 很黄很黄的网站免费的 | 91在线免费观看国产 | 久久理论电影网 | 在线看的av网站 | 成人高清在线 | 亚洲首页| 日韩高清精品免费观看 | 亚洲性少妇性猛交wwww乱大交 | 亚洲电影图片小说 | 日本 在线 视频 中文 有码 | 五月婷婷视频在线 | 久久香蕉影视 | 成人在线播放av | 97免费公开视频 | 区一区二区三在线观看 | 久久久首页 | 在线只有精品 | 国产一区国产二区在线观看 | 婷婷色中文网 | 亚洲综合色视频在线观看 | 日日天天av | 高清一区二区 | 在线观看黄av | 亚洲理论视频 | 蜜桃视频色| 亚洲精品高清视频在线观看 | 丁香五月缴情综合网 | 天天做日日爱夜夜爽 | 天天狠狠操 | 不卡的av在线 | 色婷婷导航 | 黄色特一级 | 狠狠干我 | 国产成人一二片 | 国产精品69av| 丁香六月婷婷开心婷婷网 | 国产色中涩 | 成人欧美一区二区三区在线观看 | www.亚洲黄色 | 欧美精品久久久 | 国产成人黄色网址 | 色综合天天综合在线视频 | 国产又黄又硬又爽 | 国产精品久久99精品毛片三a | 九九影视理伦片 | 一区二区三区日韩在线 | 黄色片网站av | 夜夜高潮夜夜爽国产伦精品 | av中文在线观看 | 一区二区av | 日韩 在线观看 | 四虎成人精品永久免费av九九 | 久久精品国产一区二区 | 久久免费99精品久久久久久 | 手机看片99 | 欧美日韩免费观看一区=区三区 | 免费精品国产 | 日韩午夜视频在线观看 | 久久久精品国产一区二区三区 | 国产成人三级一区二区在线观看一 | 国产精品久久久久9999 | 中文字幕在线观看一区二区 | 天天操夜夜想 | 色吊丝在线永久观看最新版本 | 亚洲一级电影 | 亚洲精品久久久久999中文字幕 | www.色午夜.com| 亚洲国产97在线精品一区 | 视频一区在线播放 | a在线免费| 婷婷激情综合网 | 国产电影一区二区三区四区 | 在线99视频 | 国产色视频一区二区三区qq号 | 亚洲资源片 | 91在线视频播放 | 四虎5151久久欧美毛片 | 99色在线观看 | 韩国在线一区二区 | 最新av网址在线观看 | 91丨porny丨九色 | 91在线免费看片 | 亚洲v精品| av免费黄色 | 国产亚州av| 亚洲一二区精品 | 国产黄在线 | 青青久草在线 | 成人wwwxxx视频 | 又黄又刺激的网站 | 中文字幕不卡在线88 | 91久久影院| 亚洲欧美日韩国产一区二区 | 97超碰资源网| 青青河边草免费直播 | 成人免费观看视频大全 | 日韩电影中文字幕在线 | 欧美成a人片在线观看久 | 黄色a一级视频 | 午夜精品久久久久久久爽 | 日韩va亚洲va欧美va久久 | 女人18片毛片90分钟 | 日韩高清黄色 | 国产精品久久久久久久久久免费 | 亚洲日本在线视频观看 | 狠狠操精品 | 一区二区三区免费在线观看 | 97成人资源站 | 激情av网址 | 亚洲视频免费 | 97视频在线播放 | 久久99精品国产99久久6尤 | a资源在线| 久草在线高清 | 国产精品久久久精品 | 国产小视频91 | 国产黄色一级大片 | 91色综合 | 69久久99精品久久久久婷婷 | 中文字幕影片免费在线观看 | 久久激情五月婷婷 | 久久九九久久九九 | 园产精品久久久久久久7电影 | 中文字幕丝袜一区二区 | 成人在线视频你懂的 | 在线观看日韩国产 | 丁香花在线视频观看免费 | 亚洲特级片 | 欧美精品午夜 | 日本久久影视 | 国产免费xvideos视频入口 | 欧美色噜噜噜 | 91精品一区二区三区久久久久久 | 亚洲区二区 | 黄色三级网站在线观看 | 日本黄色免费观看 | 中文乱码视频在线观看 | 久草五月 | 在线看国产日韩 | 亚洲四虎在线 | 日韩欧美视频一区二区三区 | 免费日韩 精品中文字幕视频在线 | 精品一区免费 | 天天操导航| 日韩欧美精品在线观看 | 超碰人人舔| 日韩中文字幕a | 久草视频中文 | 日韩精品一区二区免费视频 | 久久精品欧美一区二区三区麻豆 | 日韩视频一二三区 | 久久在线精品视频 | www.99热精品| 国产美女网 | caobi视频| 91精品欧美一区二区三区 | 999久久久久久 | 日韩精品一区二区三区电影 | 国产又粗又猛又黄又爽视频 | 国产黄色片免费 | 国产永久免费高清在线观看视频 | 男女拍拍免费视频 | 国产剧情av在线播放 | 久久久久久久久免费视频 | 国产 在线 高清 精品 | 国产精品一区二区精品视频免费看 | 正在播放五月婷婷狠狠干 | 黄色成人av| 国产亚洲精品美女久久 | 久久综合色天天久久综合图片 | 超碰com| 顶级bbw搡bbbb搡bbbb| 国产亚洲久一区二区 | 午夜美女网站 | 亚洲一区免费在线 | 天天天操天天天干 | 国产色视频一区 | 午夜精品久久久久久久99 | 精品国产一区二区三区男人吃奶 | 成全在线视频免费观看 | 91丨九色丨首页 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 人人射人人澡 | 日韩在线视频观看免费 | 97超碰人人澡 | 五月天久久激情 | 国产精品1区2区3区在线观看 | 国产亚洲人成网站在线观看 | 午夜三级影院 | 91丨九色丨国产女 | 91麻豆精品国产自产 | 国产视频 久久久 | 韩国av电影在线观看 | 99久久精品免费一区 | 日韩天天综合 | 日本视频精品 | av一本久道久久波多野结衣 | 97视频在线免费播放 | 免费黄色在线网站 | 欧美黄在线 | 在线激情av电影 | 又黄又爽又刺激 | 久久精品美女视频网站 | 欧美性精品 | 亚洲成年人av | 九九热re | 亚洲va欧美va| 国产日韩欧美中文 | 国产欧美在线一区二区三区 | 欧美一区二区在线 | 一区二区三区日韩在线观看 | 久久精品视频在线看 | 青青草视频精品 | 天天操夜操视频 | 久久免费电影网 | 天天激情天天干 | 在线国产一区二区三区 | 成人国产电影在线观看 | 日韩免费精品 | 久久黄色小说 | 在线观看色网 | 色免费在线 | 日本性xxxxx| 91在线入口 | 亚洲 欧美 精品 | 99国内精品久久久久久久 | 国产一级二级三级视频 | 久草91视频| 国产中文字幕在线看 | 欧美精选一区二区三区 | 在线高清一区 | 久久艹欧美 | 一级性视频 | 一级黄色片在线播放 | 综合色中文| 91资源在线免费观看 | 日本中文字幕在线 | 最近中文字幕免费 | 97色在线观看免费视频 | 欧美福利网站 | 亚洲成人av影片 | 日韩午夜精品福利 | 97视频精品 | 91麻豆免费看 | 在线观看黄色av | 国语精品免费视频 | 亚洲美女在线国产 | 在线观看视频免费大全 | 91香蕉视频在线下载 | 国产91aaa| 黄色一集片 | 亚洲欧美综合精品久久成人 | 一区二区三区www | 精品久久网 | www.色国产 | 99视频免费观看 | 欧美日韩久久不卡 | 日韩网站在线播放 | 精品亚洲视频在线观看 | 在线视频日韩一区 | 日韩美女久久 | 在线成人免费av | 国产精品99久久99久久久二8 | 欧美一二三视频 | 精品专区一区二区 | 五月天婷亚洲天综合网精品偷 | 成人黄色片免费看 | 免费美女av | 亚洲综合色视频在线观看 | 狠狠狠色丁香婷婷综合久久88 | 色婷婷88av视频一二三区 | 亚洲首页 | 91亚洲激情| 国产无区一区二区三麻豆 | 免费成人在线视频网站 | 黄色电影在线免费观看 | 一本一本久久a久久精品综合小说 | 久久综合久久综合这里只有精品 | 超碰999| 亚洲国产精品成人精品 | 国产v在线观看 | 久久伊99综合婷婷久久伊 | 国产亚洲视频在线观看 | 超碰在线97国产 | 狠狠操欧美 | 国产一区av在线 | 手机在线观看国产精品 | 欧美日韩免费在线视频 | 青青草国产成人99久久 | 美女久久久久 | 九九精品久久 | 久久精品视频2 | 日韩精品视频久久 | 日韩中文字幕在线观看 | 久久99亚洲精品久久久久 | 久久www免费人成看片高清 | 玖草在线观看 | 成年人在线免费看视频 | 特级毛片在线 | 免费视频黄色 | 韩国av免费看 | 日本中文字幕网站 | 天天操天天透 | 国产片免费在线观看视频 | 久久激情影院 | 国产中文视频 | 亚洲精品综合久久 | 欧美激情va永久在线播放 | 亚洲综合色丁香婷婷六月图片 | 国产精品久久久久久久久久免费 | 久久综合激情 | 一区二区不卡 | 国产精品av免费观看 | 6699私人影院| 96国产精品 | av大全免费在线观看 | 亚洲国产69 | 中文字幕免费 | 亚洲影院国产 | 亚洲精品黄色片 | 国产麻豆传媒 | 免费看污在线观看 | 欧美精品国产精品 | 久久影视中文字幕 | 日韩理论片在线观看 | 久久久国际精品 | 欧美日本中文字幕 | 久久久久久久国产精品影院 | 国产精品久久久久久久久大全 | 日本特黄特色aaa大片免费 | 久久激情综合网 | 粉嫩aⅴ一区二区三区 | 精品免费 | 久久综合久久久久88 | 久久精品二区 | 成人在线免费看 | 日本女人b | 久久精品91久久久久久再现 | 久久在线观看 | 国产精彩视频一区二区 | 成人91av| 少妇超碰在线 | 在线观看中文字幕2021 | 久久婷婷丁香 | 久久久黄色av | 免费看片网页 | 在线观看视频福利 | 久久精品视频网站 | 九九色在线观看 | 成人av在线观 | 久久久久一区二区三区四区 | 久久精品资源 | 91麻豆国产 | 主播av在线 | 怡春院av | av日韩中文 | 日本一区二区三区免费看 | 天天爱av导航 | 激情视频一区二区 | 国产91aaa | 久久影视精品 | 99久久精品国产系列 | 亚洲黄色在线观看 | 91成人精品国产刺激国语对白 | 国产高清一 | www.久久久久| 国产成人99av超碰超爽 | 亚洲国产免费网站 | 免费观看黄 | 国产乱码精品一区二区三区介绍 | www色综合 | www.黄色 | 99久久婷婷国产综合精品 | 欧美日韩激情网 | 色婷婷亚洲精品 | 五月天婷婷在线播放 | 911久久香蕉国产线看观看 | 久草网站在线 | 色狠狠狠 | 黄色视屏免费在线观看 | 在线免费黄 | 一区二区三区在线播放 | 成人性生交大片免费看中文网站 | 九九精品视频在线观看 | 日韩视频在线播放 | 色天天久久| 91精品国产欧美一区二区成人 | 久久99精品国产91久久来源 | 中文字幕精品三级久久久 | www.色午夜,com | 欧美性黑人 | 国产在线欧美 | 国产大陆亚洲精品国产 | 国内精品在线看 | 黄网站色视频免费观看 | 中日韩欧美精彩视频 | 蜜臀久久99精品久久久无需会员 | 在线看片91| 日p视频| 亚洲成人黄色在线观看 | 天天干天天草天天爽 | 国产成人精品999在线观看 | 正在播放日韩 | 特黄色大片 | av黄色免费在线观看 | 人成在线免费视频 | 国产字幕在线看 | 亚洲 成人 一区 | 日韩中文字幕视频在线 | 免费又黄又爽的视频 | 久久精品一区二 | 国产一级片免费播放 | 免费观看的黄色片 | 婷婷久月| 午夜在线观看一区 | 国产精彩视频一区二区 | 欧美韩日在线 | 久久久久久久久久久综合 | 91精品久久久久久 | 亚洲最新视频在线播放 | 亚洲乱亚洲乱亚洲 | 久久蜜臀一区二区三区av | 国产视频精品在线 | 国产成人av网站 | 在线观看免费黄视频 | 欧美性生活久久 | japanesexxx乱女另类 | 91精品国产92久久久久 | 青青草国产免费 | 欧美成人一二区 | 中国一级特黄毛片大片久久 | 国产精品综合av一区二区国产馆 | 中文字幕免费国产精品 | a精品视频 | 又爽又黄又无遮挡网站动态图 | 久久深夜 | 国产精品热视频 | 精品视频中文字幕 | 婷婷六月丁香激情 | 免费激情网 | 国产一级在线免费观看 | 久草在线视频中文 | 国产精品福利在线播放 | 欧美性一级观看 | 久久手机精品视频 | 一区二区精| 日操操 | 久久免费国产视频 | 精品久久一区二区 | 亚洲一区二区91 | 日韩在线观看一区二区 | 国产精品久久久久久婷婷天堂 | 亚洲成a人片在线观看网站口工 | 国产又粗又猛又爽又黄的视频先 | 久久国产精品99久久久久久丝袜 | 亚洲一区 影院 | 国产精品综合久久久 | 亚洲国产精品一区二区久久hs | 日韩一区二区三区高清在线观看 | 91精品国产99久久久久久红楼 | 亚洲欧洲精品视频 | 中文字幕在线网 | 久久久久久久国产精品影院 | 操操综合 | 国产一区欧美在线 | 色婷婷狠狠干 | 欧美性黑人 | avav99| 成人啊 v | 欧美俄罗斯性视频 | 日日摸日日添夜夜爽97 | 激情在线网址 | 98涩涩国产露脸精品国产网 | 久久综合中文字幕 | 日韩在线视频国产 | av综合av| 91av在线精品| av电影免费在线播放 | 国产r级在线观看 | 四虎www com| 激情五月婷婷 | 麻豆你懂的 | 精品国产伦一区二区三区观看方式 | 麻豆视频91| 欧美亚洲精品在线观看 | 综合天堂av久久久久久久 | 在线观看免费色 | 国内视频一区二区 | 午夜黄网 | 中文字幕888 | 国产精品成人久久久 | 欧美日韩在线观看一区二区三区 | 午夜精品福利在线 | 日批在线观看 | 欧美 日韩 国产 中文字幕 | 日韩电影一区二区三区 | 亚洲精品综合一二三区在线观看 | 色综合国产 | 在线激情av电影 | 91在线网站| 男女啪啪网站 | 欧美精品二区 | 精品黄色在线 | 久久久久久久久久久网 | 国产高清视频免费观看 | 人人澡超碰碰97碰碰碰软件 | 在线观看成人小视频 | 91片在线观看 | 热99久久精品 | 500部大龄熟乱视频使用方法 | 韩日电影在线免费看 | 99re久久资源最新地址 | 日韩欧美精品一区二区三区经典 | 国产免费av一区二区三区 | 黄色最新网址 | 国产精品电影在线 | 久草视频在线免费播放 | 国产999精品视频 | 国产黄色片在线 | 国产精品久久久999 国产91九色视频 | 久久免费在线 | 久久精品视频网 | 色91在线| 国产成人三级在线 | 久久99欧美| 国产成人一区二区三区在线观看 | 欧美性粗大hdvideo | 四虎影视国产精品免费久久 | 午夜男人影院 | 欧美激情精品久久久久久免费印度 | 欧美成人中文字幕 | www.黄色片.com| 伊人开心激情 | 国产精品美女免费 | 国内精品久久久久久久影视简单 | 久草视频在线播放 | 欧美一级免费 | 四虎影视久久久 | 日本黄色一级电影 | 国产美女视频免费 | 一级片免费在线 | 日本三级在线观看中文字 | 91亚洲国产成人久久精品网站 | 国产高清在线免费观看 | 国产精品欧美日韩 | 久久观看免费视频 | 日av免费 | 黄在线| 免费成人在线视频网站 | 国产精品久久电影观看 | 久草在线视频新 | 激情欧美xxxx| 欧美精品在线一区二区 | 天天干天天干天天操 | 三级av免费看 | 国内成人精品视频 | 三级免费黄 | 一本一道久久a久久精品 | 亚洲最新合集 | 日韩在线中文字幕视频 | 国产一区二区三精品久久久无广告 | 五月天视频网站 | 久久久久99精品成人片三人毛片 | 黄色网www| 色婷婷av在线 | 午夜美女视频 | 人人插人人做 | 欧美在线视频a | 亚洲综合精品在线 | 日韩精品一区二区在线视频 | 91手机视频在线 | 手机av在线网站 | av三级在线免费观看 | 五月激情五月激情 | 国产精品久久久久久久久久白浆 | 精品国产网址 | 国产精品成人在线 | 久草干| 国产精品久久久久久久久久久久久久 | 偷拍精品一区二区三区 | 草久在线视频 | 国产v欧美 | 高清在线一区 | 国产在线专区 | 9999亚洲| 久久成人国产精品入口 | 99麻豆视频 | 国产亚洲精品久久久久久大师 | 亚洲妇女av | 美女国产免费 | 久久久久久久久影院 | 婷婷www| 亚洲免费不卡 | 亚洲国产午夜精品 | 国产精品久久嫩一区二区免费 | 人人干人人做 | 中文字幕在线免费观看视频 | 国产精品视频地址 | 中国一级片视频 | 国产又粗又猛又黄又爽 | 在线视频99 | 欧美久久久一区二区三区 | 久久久久久久亚洲精品 | 久久精品观看 | 天天爽夜夜爽精品视频婷婷 | 97人人添人澡人人爽超碰动图 | 国产精品久久久久久久久久免费看 | 在线免费色视频 | 2020天天干夜夜爽 | 91高清视频免费 | 一区二区 不卡 | 免费人人干 | 国产五月色婷婷六月丁香视频 | 天天色天天干天天色 | 中文在线a√在线 | 99看视频在线观看 | 97国产小视频 | 在线国产视频观看 | 天天综合91 | 中文一二区 | 中文字幕久久精品 | 久久视屏网| 中文字幕电影高清在线观看 | 中文字幕一区二区在线播放 | 丝袜美腿亚洲综合 | 久久国产精品99国产精 | 在线91观看 | 天天综合天天做天天综合 | 五月综合激情网 | 亚洲www天堂com | 免费看污在线观看 | 中文字幕高清免费日韩视频在线 | 最近日本字幕mv免费观看在线 | 久草在线播放视频 | 免费看成人a | 三上悠亚一区二区在线观看 | 精品免费| 亚洲欧洲成人精品av97 | 天天弄天天操 | 精品国产一区二区三区久久久蜜臀 | 中文字幕在线视频国产 | 在线视频观看你懂的 | 麻豆影音先锋 | 亚洲视频在线播放 | 日韩av电影中文字幕在线观看 | 国产精品久久久久久久久久了 | 深爱激情五月婷婷 | 丝袜+亚洲+另类+欧美+变态 | www国产在线 | 欧美9999| 黄污网站在线观看 | 成人午夜电影在线观看 | 国产一区二区在线免费视频 | 国产高清视频网 | 亚洲综合色丁香婷婷六月图片 | 亚洲国产日韩在线 | 国产精品久久久网站 | 91综合在线| 成人h在线观看 | 天天亚洲综合 | 成人免费看片98欧美 | 亚洲精品国产精品久久99 | 国产精彩视频 | 久久精品影片 | 久久精品国产一区二区 | 国产一区二区三区免费观看视频 | 亚州精品天堂中文字幕 | 亚洲永久国产精品 | 亚洲黑丝少妇 | 国产视频久久久 | 97精品久久人人爽人人爽 | 中文av免费| 国产亚洲综合精品 | 国产原创av片 | 国产手机视频 | 99久热在线精品视频成人一区 | 日韩欧美在线观看一区二区三区 | 丁香色天天 | 久久影院午夜论 | 91看毛片 | 日本bbbb摸bbbb| 色欧美88888久久久久久影院 | 日韩欧美在线不卡 | 国产欧美久久久精品影院 | 国产精品一区二区三区视频免费 | 99综合电影在线视频 | 在线免费色视频 | 99这里只有精品99 | 在线免费黄色毛片 | 亚洲一区在线看 | h视频在线看| 嫩嫩影院理论片 | 亚洲国产精久久久久久久 | 毛片二区| 日韩在线免费小视频 | 9在线观看免费高清完整 | 日本aaaa级毛片在线看 | 亚洲精品videossex少妇 | 亚洲人成人在线 | 亚洲一区二区三区miaa149 | 国产成人性色生活片 | 国产裸体bbb视频 | 国内亚洲精品 | 99视频免费| 九九热re | 欧美性免费 | 国精产品一二三线999 | 日韩精品专区 | 成人午夜影院 | 成年人黄色在线观看 | 久久免费看av | 成人免费观看网址 | 欧美日韩不卡一区二区三区 | 国内精品久久久久 | 久久综合国产伦精品免费 | 人人干,人人爽 | 亚洲精品婷婷 | 国产小视频免费观看 | 免费视频一级片 | 午夜黄色一级片 | 欧美成人xxxxxxxx| 亚洲国产综合在线 | 九色自拍视频 | 99人久久精品视频最新地址 | 国产剧情一区二区在线观看 | 中文字幕精品三区 | 最近免费观看的电影完整版 | 黄色毛片视频免费 | 91污污视频在线观看 | 色噜噜在线观看 | 中文字幕精品一区 | 在线观看岛国av | 九九九九精品 | 久久久久亚洲精品中文字幕 | 一区二区中文字幕在线播放 | 欧美精品在线观看免费 | 国产手机视频在线播放 | 欧美一二三区在线播放 | 91 中文字幕 | 国产精品一区二区果冻传媒 | 天天爱天天草 | 青草视频在线免费 | 婷婷色亚洲| 五月婷婷综合在线观看 | 亚洲欧美精品一区 | 免费久久久久久久 | 人人揉人人揉人人揉人人揉97 | 91看片网址 | 手机看片福利 | 婷婷六月丁香激情 | 不卡国产视频 | 国产无遮挡猛进猛出免费软件 | 在线观看免费高清视频大全追剧 | 97热视频 | 亚洲最大av | 欧美一级裸体视频 | 超碰在线免费福利 | 国产一级在线免费观看 | av观看免费在线 | 久久综合久久综合这里只有精品 | 日日添夜夜添 | 天天干夜夜爱 | 国产精品一区专区欧美日韩 | 亚洲成av人影片在线观看 | 91网在线看 | 日韩精品欧美专区 | 天天摸夜夜操 | 91视频 - v11av | 人人射人人射 | 欧美精品免费视频 | 国产精品精品国产色婷婷 | 国产免费亚洲 | 91九色蝌蚪国产 | 夜夜躁狠狠躁日日躁 | 日韩精品一区二区三区水蜜桃 | 中文国产字幕在线观看 | 伊人五月天 | 五月婷亚洲 | 黄色网在线播放 | 久久超碰网 | 久久综合五月 | 91精品国产高清 | 国产日韩一区在线 | 国产高清不卡一区二区三区 | 亚洲免费国产视频 | 成人午夜电影网站 | 久久久九色精品国产一区二区三区 | 亚洲久草网 | 久久精品美女视频网站 | 国产精品久久久久久妇 | 久久精品99北条麻妃 | 精品中文字幕在线观看 | 成人网看片 | 九九久久国产精品 | 五月天,com | 狠狠躁夜夜躁人人爽视频 | 奇米先锋 | 2020天天干夜夜爽 | 国产一区精品在线观看 | 久久综合中文字幕 | 久草精品视频在线观看 | 日韩高清成人 | 视频一区二区免费 | 美女黄濒 | 在线亚洲午夜片av大片 | 97日日 | 天天天操操操 | 人人爽人人看 | 亚洲精品xx | 中文字幕国语官网在线视频 | 国产在线免费观看 | a级片在线播放 | 97操碰 | 日本黄网站 | 综合黄色网 | 亚洲 欧美 91 | av中文字幕第一页 | 中文字幕在线日本 | 一区二区三区日韩视频在线观看 | 97偷拍在线视频 | 免费a视频在线观看 | 五月婷婷中文网 | 日韩激情视频在线观看 | 国产一性一爱一乱一交 | 日韩欧美国产免费播放 | 亚洲精品乱码久久久久久 | 日韩精品2区 | 五月天国产 | 日韩在线网 | 国产大片免费久久 | 国产精品毛片久久久久久久久久99999999 | 激情网站免费观看 | 在线一级片 | 99久久久久久久久久 | 97在线观视频免费观看 | 国产又粗又猛又黄 | 黄网站色视频 | 久久久久久久免费看 | 日韩精品无 | 亚洲精品视频免费观看 | 特级黄录像视频 | 久久午夜电影 | 免费高清在线观看成人 | 天天爱天天舔 | 日本h在线播放 | 96国产精品视频 | 欧美三级免费 | 亚洲精品免费在线观看 | 色黄www小说 | 国产中文字幕一区 | 福利视频入口 | 在线小视频你懂的 | 麻花传媒mv免费观看 | 在线天堂日本 | 午夜色站 | 在线观看国产一区二区 | 在线国产视频 | а中文在线天堂 | 精品黄色在线观看 | 欧美福利视频一区 | 九九视频在线观看视频6 | 免费在线观看91 | 国产成人精品不卡 | 五月香视频在线观看 | 在线亚洲日本 | 热久久视久久精品18亚洲精品 | 91视频高清免费 | 日韩精品第一区 | 免费观看一级一片 | 亚洲区视频在线 | 韩国精品在线观看 | 国产精品久久久久久一区二区三区 | 欧美在线你懂的 | 人人玩人人添人人澡97 | 香蕉视频4aa| 日韩系列在线 | 亚洲免费av片 | 久久久亚洲麻豆日韩精品一区三区 | 午夜视频日本 | 亚洲一级电影在线观看 | 97成人啪啪网 | 亚州国产视频 | 开心丁香婷婷深爱五月 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 国产一区二区精品91 | 国产黄色av网站 | 久久激情五月丁香伊人 | 久久99久久99 | 在线视频婷婷 | 五月天色婷婷丁香 | 国产日产高清dvd碟片 | 西西人体www444| 国产又粗又长的视频 | 午夜影院在线观看18 | 日韩精品在线视频 | 日韩 在线观看 | av一区二区三区在线观看 | 久草在线国产 | 精品久久久久久亚洲综合网 | 日韩高清免费在线 | 日韩av男人的天堂 | 久久久久国产一区二区三区 | 韩国一区在线 | 欧美精品午夜 | av在线播放不卡 | 久久国产福利 | 国内精品亚洲 | 欧美二区视频 | 久久大片网站 | 久久久综合色 | 国产精品一区二区三区免费视频 | 成年人在线观看网站 | 91久久丝袜国产露脸动漫 | 免费手机黄色网址 | 草草草影院 | 国产日韩在线播放 | 51精品国自产在线 | 免费视频在线观看网站 | 亚洲精品自拍视频在线观看 | 欧美精品一区在线发布 | 免费一级片久久 | 成人黄色大片在线免费观看 | 久草在线电影网 | jizz18欧美18 | 精品一区在线 | 国产午夜精品一区二区三区在线观看 | 日韩.com| 欧美天天综合网 | 91av视频在线免费观看 | 热精品 | 少妇视频一区 | 亚洲va韩国va欧美va精四季 | 婷婷九九| 天天舔夜夜操 | 欧美日韩视频一区二区三区 | 五月婷在线视频 | 97视频免费 | 国产精品麻 | 亚洲精品综合在线 | 91在线播放视频 | 9草在线 | 日韩精品视频免费看 | 国产高清一区二区 | 最新av免费在线观看 | 成人在线免费观看网站 | 蜜臀av网址| 91精品老司机久久一区啪 | 精品国产一区二区三区男人吃奶 | 久久精品视频在线看 | 亚洲女同ⅹxx女同tv | 午夜电影一区 | 亚洲欧洲精品视频 | 久久影视精品 | 欧美一级免费 | 日韩剧 | 精品国产一区二区三区久久 | 在线观看视频在线 | 久久久精品国产免费观看同学 | 国产精品久久久久久久久久直播 | 亚洲精选在线 | 色综合久久中文字幕综合网 | 日韩精品中文字幕在线不卡尤物 | www.看片网站 | 日日日爽爽爽 | 操操操com| 久草99| 性色va| 在线观看国产中文字幕 | 久久综合九色欧美综合狠狠 | 久久新| 久久久久久久久久久久久国产精品 | 五月婷婷六月丁香激情 | 国产一级片免费观看 | 日韩毛片久久久 | av中文在线影视 | 国产成人免费观看久久久 | 欧美日韩伦理一区 | 国产不卡在线视频 | 成人午夜av电影 | 少妇资源站 | 视色网站| 久久精品国产成人精品 | 99精品免费在线观看 | 中文字幕亚洲精品在线观看 |