QQ通信原理分析

 下面有4個基本的問答:

問題一:爲什麼只要可以連上互聯網的計算機都可以用QQ相互建立通信,而不需要固定IP?
也就是這個QQ用戶端是怎樣找到另一個QQ用戶的,而用戶在每次使用時他可能用的是不同的計算機,有着不同的IP地址。
服務器端不會以qq用戶端的ip作爲唯一標識,服務器端會以qq賬號作爲唯一標識,所以這個賬號肯定是唯一的,一個賬號登陸時每次都可以有不同的ip地址,但賬號卻相同,當賬號a登陸服務器,服務器會記錄下賬號a的ip地址,去通知a的好友,告訴他們,a上線了和現在的ip地址,a的好友就可以跟他通信了

問題二:是不是QQ在通信時根本不適用IP,QQ客戶端先是訪問QQ服務器端,然後QQ服務器端再爲要建立連接的QQ客戶端建立連接?
只要是網絡層的通信,都會涉及到ip/tcp協議,就肯定需要ip,qq客戶端登陸qq服務器,服務器只是記錄登陸狀態,不會一直和qq保持通信,只會每隔一段時間發送心跳數據包,來確實qq客戶端是否還在網絡上。當qq客戶端a上線後,服務器會告訴a,目前a的在線好友的最新ip地址,當a需要與任意好友通信時,直接使用ip地址就ok了。qq客戶端a與qq客戶端b通信,可以兩種方式,第一就是qq服務器有轉發的服務器,第二是,a與b直接通信,不會告訴qq服務器
問題三:QQ客戶端可以訪問QQ服務器端,然後服務器端獲取QQ客戶端的IP建立通信,是不是這樣的過程。。。如果是,這個過程是怎麼處理的呢?
是這樣的過程,qq客戶端請求一個連接給服務器,服務器接收後,知道qq端a上線,把qq端a的賬號跟目前的ip會記錄下來,放在在線列表裏或者其他的地方,然後每隔幾分鐘或者幾秒鐘給qq端a發送心跳包,問他是否還在線,來確保qq端a的最新狀態。這裏客戶端與服務器的通信方式是udp。而不會時時刻刻都在用tcp連接。
問題四:QQ客戶端雖然IP地址不固定,但是在建立與QQ服務器端的通信時,必須提供自己的IP被服務器獲取,然後才能建立他們之間的通信,進而在建立客戶端之間的通信。也就是,只要能上網就有IP,只不過客戶端的IP,是被QQ客戶端獲取了,然後才建立通信的。(這是自己的猜測,不知對否。。。)
恩,服務器不會以ip作爲唯一標識,會以賬號作爲唯一標識,但與賬號通信的時候會用到賬號目前所對應的ip,客戶端與客戶端通信也如此

QQ有兩種登陸模式
一種是比較不常用的:直接登陸服務器,所有信息由服務器轉發,這種登陸模式有個特點就是你會發現你使用獲取IP版本的QQ無法獲取對方的IP~ (這個我不清楚有沒有,但是肯定可以)
另一種是普通的:首先連接登陸服務器,在給對發發消息的時候,首先嚐試與對方進行打洞連接,如果可以打通消息直接發送給對方,如果不能打通,則消息轉發服務器,由服務器轉發.(傳文件會優先P2P,不行再選擇中轉,不知道聊天是不是優先P2P的,還是聊天文字是中轉的?圖片呢?會員表情?這個的確要問tx了,技術上的都是可以實現,選擇什麼只能問tx了)

如果上面的東西輕鬆搞定,那麼你可以繼續看了,如果不知道,那麼下面就不用看了

 

先貼一點資料

一、登陸。

不管UDP還是TCP,最終登陸成功之後,QQ都會有一個TCP連接來保持在線狀態。這個TCP連接的遠程端口一般是80,採用UDP方式登陸的時候,端口是8000。因此,假如你所在的網絡開放了80端口(80端口是最常用端口。。就是通常訪問Web的端口,禁掉它的話,你的網絡對你來說價值已經不大了),但沒有屏蔽騰訊的服務器IP,恭喜你,你是可以登陸成功QQ的。
二、聊天消息通信。
採用UDP協議,通過服務器中轉方式。因此,現在的IP偵探在你僅僅跟對方發送聊天消息的時候是無法獲取到IP的。大家都知道,UDP 協議是不可靠協議,它只管發送,不管對方是否收到的,但它的傳輸很高效。但是,作爲聊天軟件,怎麼可以採用這樣的不可靠方式來傳輸消息呢?於是,騰訊採用了上層協議來保證可靠傳輸:如果客戶端使用UDP協議發出消息後,服務器收到該包,需要使用UDP協議發回一個應答包。如此來保證消息可以無遺漏傳輸。之所以會發生在客戶端明明看到“消息發送失敗”但對方又收到了這個消息的情況,就是因爲客戶端發出的消息服務器已經收到並轉發成功,但客戶端由於網絡原因沒有收到服務器的應答包引起的。
三、文件/自定義表情傳送。
大家都知道,QQ可以傳送文件,可以發送自定義表情。先說官方表情。官方表情實際發送的是命令字,而沒有發送表情。客戶端收到命令字後,會自動解釋爲對應的表情。因此,QQ2008正式版的客戶端發出的新版表情,在2007beta4及以前的版本無法找到相對應的表情,就無法解釋,看到的就會是空白信息,但查聊天記錄就會有[表情]字樣。
自定義表情的傳送是以文件傳輸方式進行的。
下面說文件傳輸方式:A要向B發送一個文件,於是發出一個文件傳送請求。服務器收到這個文件傳送請求後,轉發給B,同時或者在B應答後,將A的IP地址同時發送給B。B這個時候就得到了A的真實IP。這裏的IP是你的本機IP。也就是說,如果A處在內網,B得到的地址就是一個內網地址。B得到了A的地址之後,就會嘗試去連接A。如果B也處於內網,那麼,顯然A跟B之間的連接是無法建立的。這個時候,客戶端就會請求服務器進行文件中轉。因爲服務器具有公網 IP,處在內網的A跟B都是可以連接到服務器的,於是,A跟B的文件傳送就通過服務器中轉的方式,順利進行。(注:服務器文件中轉使用443端口)

其實紅字部分是不正確的,QQ的文件傳輸採用的是P2P,也就是爲什麼在相同局域網下,兩個人用QQ傳文件會非常快,這裏用到的是NAT打洞技術,下面我會詳細的說明

無論是傳文件還是聊天文字技術上都可以使用P2P,P2P 都可以用UDP實現,而UDP在NAT打洞上面更加方便和成熟,所以騰訊應該是優先UDP,但是使用UDP爲了增加可靠性,尤其是傳文件,就要用到UDP模擬TCP ,也就是他所謂的新TCP,看來在UDP安全通信方面,騰訊應該很牛逼了

下面只說的技術,具體QQ是不是這樣的只能問騰訊了

(TCP與UDP的打洞技術過程基本相同,支持TCP打洞的nat設備不多,洞其實就是socket,udp和tcp的socket api的問題,具體以後寫文章研究一下)

* 注:什麼是內網、公網
內網、公網是兩種Internet的接入方式。
內網接入方式:上網的計算機得到的IP地址是Inetnet上的保留地址,保留地址有如下3種形式:
10.x.x.x(學校內網)
172.16.x.x至172.31.x.x
192.168.x.x(自用路由)
內網的計算機以NAT(網絡地址轉換)協議,通過一個公共的網關訪問Internet。
內網的計算機可向Internet上的其他計算機發送連接請求,但Internet上其他的計算機無法向內網的計算機發送連接請求。
公網接入方式:上網的計算機得到的IP地址是Inetnet上的非保留地址。公網的計算機和Internet上的其他計算機可隨意互相訪問。

*注:Nat技術基礎

NAT(Network Address Translators),網絡地址轉換:網絡地址轉換是在IP地址日益缺乏的情況下產生的,它的主要目的就是爲了能夠地址重用。NAT分爲兩大類,基本的NAT和NAPT(Network Address/Port Translator)。

最開始NAT是運行在路由器上的一個功能模塊。

最先提出的是基本的NAT,它的產生基於如下事實:一個私有網絡(域)中的節點中只有很少的節點需要與外網連接(呵呵,這是在上世紀90年代中期提出的)。那麼這個子網中其實只有少數的節點需要全球唯一的IP地址,其他的節點的IP地址應該是可以重用的。
因此,基本的NAT實現的功能很簡單,在子網內使用一個保留的IP子網段,這些IP對外是不可見的。子網內只有少數一些IP地址可以對應到真正全球唯一的IP地址。如果這些節點需要訪問外部網絡,那麼基本NAT就負責將這個節點的子網內IP轉化爲一個全球唯一的IP然後發送出去。(基本的NAT會改變IP包中的原IP地址,但是不會改變IP包中的端口)
關於基本的NAT可以參看RFC 1631

另外一種NAT叫做NAPT,從名稱上我們也可以看得出,NAPT不但會改變經過這個NAT設備的IP數據報的IP地址,還會改變IP數據報的TCP/UDP端口。基本NAT的設備可能我們見的不多(呵呵,我沒有見到過),NAPT纔是我們真正討論的主角。

Client A
10.0.0.1:1234

A是其中的一臺計算機,這個網絡的網關(一個NAT設備)的外網IP是155.99.25.11(應該還有一個內網的IP地址,比如10.0.0.10)。

如果Client A中的某個進程(這個進程創建了一個UDP Socket,這個Socket綁定1234端口)想訪問外網主機18.181.0.31的1235端口,那麼當數據包通過NAT時會發生什麼事情呢?

首先NAT會改變這個數據包的原IP地址,改爲155.99.25.11。

接着NAT會爲這個傳輸創建一個Session(Session是一個抽象的概念,如果是TCP,也許Session是由一個SYN包開始,以一個FIN包結束。而UDP呢,以這個IP的這個端口的第一個UDP開始,結束呢,呵呵,也許是幾分鐘,也許是幾小時,這要看具體的實現了)並且給這個Session分配一個端口,比如62000,然後改變這個數據包的源端口爲62000。所以本來是(10.0.0.1:1234->18.181.0.31:1235)的數據包到了互聯網上變爲了(155.99.25.11:62000->18.181.0.31:1235)。

一旦NAT創建了一個Session後,NAT會記住62000端口對應的是10.0.0.1的1234端口,以後從18.181.0.31發送到62000端口的數據會被NAT自動的轉發到10.0.0.1上。(注意:這裏是說18.181.0.31發送到62000端口的數據會被轉發,其他的IP發送到這個端口的數據將被NAT拋棄)這樣Client A就與Server S1建立以了一個連接。

首先如果兩個機子全部在外網,也就是他們可以直接相連,那麼P2P一點問題也沒有

第二如果兩個機子一個是內網A,一個是外網B

1.如果內網的主動想外網的請求連接,那麼連接就像上面的解釋一樣

2.但是洞只能有內網來打,洞是有方向性的(session保存這個信息),所以當外網的想主動和內網的連接時,就需要中介服務器,服務器通知內網A向B打洞來建立連接

第三如果兩個機子一個是內網A,另一個是另外一個內網B

網絡環境描述:
內網1NAT:NAT1/218.7.32.28
內網1中一臺主機A:ClientA/192.168.1.128
內網2NAT:NAT2/218.7.31.221
內網2中一臺主機B:ClientB/192.168.0.5
公網服務器:Server

 

首先讓ClientA和ClientB登錄到服務器Server(假如兩臺主機都採用2347端口),此時NAT1和NAT2會分別爲ClientA和 ClientB打開一個指向Server的洞(NAT1上218.7.32.28:26756和NAT2上218.7.31.221:27550)。服務器應改記錄這兩個客戶端的信息(關鍵是那兩個洞的信息)。當ClientA與ClientB要建立會話時,ClientA首先用2347端口向NAT2的洞發送一個數據包,當然這個數據包會被NAT2所丟棄,但是由於這是從NAT1內部向外部發送數據,所以NAT1爲ClientA打開了一個指向NAT2 的洞。而且這個新洞與原來NAT1上指向Server的舊洞的是同一個洞(因爲是同一個端口26756),所以這裏可以說這個洞具有了兩個方向(關鍵),同時指向 Server和NAT2。這時ClientA應該通知Server,告訴ClientB,現在可以向NAT1的那個洞 (218.7.32.28:26756)發送數據包了。當ClientB向NAT1的那個洞發送數據以後,NAT2也爲ClientB打了一個指向 NAT1的洞,這是可以說ClientA與ClientB的會話就建立完成了,他們可以不依賴Server進行通信了。如果以後ClientA和 ClientB還需要建立其他會話 ,那麼這個牽線的“媒人”可以不是Server,而可以是ClientA或ClientB了。

第四如果兩個機子都是同一個內網

用上面的方法肯定可以,那麼如果NAT支持loopback(就是本地到本地的轉換),A,B可以連接,但是比較浪費帶寬和NAT,一般的時候都不會用loopback,會直接內網P2P(我覺得QQ客戶端可以做一下判斷以選擇內網直接P2P)

注:

NAT對session的處理

以下分析NAPT是依據什麼策略來判斷是否要爲一個請求發出的UDP數據包建立Session的.主要有一下幾個策略:

A. 源地址(內網IP地址)不同,忽略其它因素, 在NAPT上肯定對應不同的Session

B. 源地址(內網IP地址)相同,源端口不同,忽略其它的因素,則在NAPT上也肯定對應不同的Session

C. 源地址(內網IP地址)相同,源端口相同,目的地址(公網IP地址)相同,目的端口不同,則在NAPT上肯定對應同一個Session

D. 源地址(內網IP地址)相同,源端口相同,目的地址(公網IP地址)不同,忽略目的端口,則在NAPT上是如何處理Session的呢?(這個要根據下面NAT的種類區別,Cone相同,Symmetic不同)

NAT分類

根據Stun協議(RFC3489),NAT大致分爲下面四類

 

 

 

 

 

1)      Full Cone

 

 

這種NAT內部的機器A連接過外網機器C後,NAT會打開一個端口.然後外網的任何發到這個打開的端口的UDP數據報都可以到達A.不管是不是C發過來的.

例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88

A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)

任何發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)

2)      Restricted Cone

這種NAT內部的機器A連接過外網的機器C後,NAT打開一個端口.然後C可以用任何端口和A通信.其他的外網機器不行.

例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88

A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)

任何從C發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)

3)      Port Restricted Cone

這種NAT內部的機器A連接過外網的機器C後,NAT打開一個端口.然後C可以用原來的端口和A通信.其他的外網機器不行.

例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88

A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)

C(202.88.88.88:2000)發送到 NAT(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)

以上三種NAT通稱Cone NAT.我們只能用這種NAT進行UDP打洞.

4)      Symmetic

 

 

 

對於這種NAT.連接不同的外部目標.原來NAT打開的端口會變化.而Cone NAT不會.雖然可以用端口猜測.但是成功的概率很小.因此放棄這種NAT的UDP打洞.

 

 

第一種情況, 雙方都是Symmetric NAPT:

此情況應給不存在什麼問題,肯定是不支持UDP穿透。

第二種情況, 雙方都是Cone NAPT:

此情況是我們需要的,可以進行UDP穿透。

第三種情況, 一個是Symmetric NAPT, 一個是Cone NAPT:

這個行不行呢,這個問題留給大家吧   來源 http://softpalace.co.de/?p=279


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章