面試筆試--TCP/IP知識點

下面的圖表試圖顯示不同的TCP/IP和其他的協議在最初OSI模型中的位置:

7 應用層 例如HTTPSMTPSNMPFTPTelnetSIPSSHNFSRTSPXMPPWhoisENRP
6 表示層 例如XDRASN.1SMBAFPNCP
5 會話層 例如ASAPTLSSSH、ISO 8327 / CCITT X.225、RPCNetBIOSASPWinsockBSD sockets
4 傳輸層 例如TCPUDPRTPSCTPSPXATPIL
3 網絡層 例如IPICMPIGMPIPXBGPOSPFRIPIGRPEIGRPARPRARP、 X.25
2 數據鏈路層 例如EthernetToken ringHDLCFrame relayISDNATM802.11 WiFiFDDIPPP
1 物理層 例如wireradiofiber opticCarrier pigeon

通常人們認爲OSI模型的最上面三層(應用層、表示層和會話層)在TCP/IP組中是一個應用層。由於TCP/IP有一個相對較弱的會話層,由TCP和RTP下的打開和關閉連接組成,並且在TCP和UDP下的各種應用提供不同的端口號,這些功能能夠被單個的應用程序(或者那些應用程序所使用的庫)增加。與此相似的是,IP是按照將它下面的網絡當作一個黑盒子的思想設計的,這樣在討論TCP/IP的時候就可以把它當作一個獨立的層。

4 應用層
(OSI
5 到 7層)
例如HTTPFTPDNS
(如BGPRIP這樣的路由協議,儘管由於各種各樣的原因它們分別運行在TCP和UDP上,仍然可以將它們看作網絡層的一部分)
3 傳輸層
(OSI
4 和 5層)
例如TCPUDPRTPSCTP
(如OSPF這樣的路由協議,儘管運行在IP上也可以看作是網絡層的一部分)
2 網絡互連層
(OSI
3層)
對於TCP/IP來說這是因特網協議(IP)
(如ICMPIGMP這樣的必須協議儘管運行在IP上,也仍然可以看作是網絡互連層的一部分;ARP不運行在IP上)
1 網絡接口層
(OSI
1和2層)
例如EthernetWi-FiMPLS等。

應用層

該層包括所有和應用程序協同工作,利用基礎網絡交換應用程序專用的數據的協議。 應用層是大多數普通與網絡相關的程序爲了通過網絡與其他程序通信所使用的層。這個層的處理過程是應用特有的;數據從網絡相關的程序以這種應用內部使用的格式進行傳送,然後被編碼成標準協議的格式。

一些特定的程序被認爲運行在這個層上。它們提供服務直接支持用戶應用。這些程序和它們對應的協議包括HTTP(The World Wide Web)、FTP(文件傳輸)、SMTP(電子郵件)、SSH(安全遠程登陸)、DNS(名稱<-> IP 地址尋找)以及許多其他協議。

一旦從應用程序來的數據被編碼成一個標準的應用層協議,它將被傳送到IP棧的下一層。

傳輸層

在傳輸層,應用程序最常用的是TCP或者UDP,並且服務器應用程序經常與一個公開的端口號相聯繫。服務器應用程序的端口由Internet Assigned Numbers Authority(IANA)正式地分配,但是現今一些新協議的開發者經常選擇它們自己的端口號。由於在同一個系統上很少超過少數幾個的服務器應用,端口衝突引起的問題很少。應用軟件通常也允許用戶強制性地指定端口號作爲運行參數

連結外部的客戶端程序通常使用系統分配的一個隨機端口號。監聽一個端口並且然後通過服務器將那個端口發送到應用的另外一個副本以建立對等連結(如IRC上的dcc文件傳輸)的應用也可以使用一個隨機端口,但是應用程序通常允許定義一個特定的端口範圍的規範以允許端口能夠通過實現網絡地址轉換(NAT)的路由器映射到內部。

每一個應用層(TCP/IP參考模型 的最高層)協議一般都會使用到兩個傳輸層協議之一: 面向連接的TCP傳輸控制協議和無連接的包傳輸的UDP用戶數據報文協議 。

常用的應用層協議有

運行在TCP協議上的協議:
  • HTTP(Hypertext Transfer Protocol,超文本傳輸協議),主要用於普通瀏覽。
  • HTTPS(Hypertext Transfer Protocol over Secure Socket Layer, or HTTP over SSL,安全超文本傳輸協議),HTTP協議的安全版本。
  • FTP(File Transfer Protocol,文件傳輸協議),由名知義,用於文件傳輸。
  • POP3(Post Office Protocol, version 3,郵局協議),收郵件用。
  • SMTP(Simple Mail Transfer Protocol,簡單郵件傳輸協議),用來發送電子郵件 。
  • TELNET(Teletype over the Network,網絡電傳),通過一個終端(terminal)登陸到網絡。
  • SSH(Secure Shell,用於替代安全性差的TELNET),用於加密安全登陸用。
運行在UDP協議上的協議:
  • BOOTP(Boot Protocol,啓動協議),應用於無盤設備。
  • NTP(Network Time Protocol,網絡時間協議),用於網絡同步。
其他:
  • DNS(Domain Name Service,域名服務),用於完成地址查找,郵件轉發等工作(運行在TCPUDP協議上)。
  • ECHO(Echo Protocol,迴繞協議),用於查錯及測量應答時間(運行在TCPUDP協議上)。
  • SNMP(Simple Network Management Protocol,簡單網絡管理協議),用於網絡信息的收集和網絡管理。
  • DHCP(Dynamic Host Configuration Protocol,動態主機配置協議),動態配置IP地址。
  • ARP(Address Resolution Protocol,地址解析協議),用於動態解析以太網硬件的地址。


傳輸層的協議,能夠解決諸如可靠性(“數據是否已經到達目的地?”)和保證數據按照正確的順序到達這樣的問題。在TCP/IP協議組中,傳輸協議也包括所給數據應該送給哪個應用程序。

在TCP/IP協議組中技術上位於這個層的動態路由協議通常被認爲是網絡層的一部分;一個例子就是OSPF(IP協議89)。

TCP(IP協議6)是一個“可靠的”、面向連結的傳輸機制,它提供一種可靠的字節流保證數據完整、無損並且按順序到達。TCP儘量連續不斷地測試網絡的負載並且控制發送數據的速度以避免網絡過載。另外,TCP試圖將數據按照規定的順序發送。這是它與UDP不同之處,這在實時數據流或者路由高網絡層丟失率應用的時候可能成爲一個缺陷。

較新的SCTP也是一個“可靠的”、面向連結的傳輸機制。它是面向紀錄而不是面向字節的,它在一個單獨的連結上提供了通過多路複用提供的多個子流。它也提供了多路自尋址支持,其中連結終端能夠被多個IP地址表示(代表多個物理接口),這樣的話即使其中一個連接失敗了也不中斷。它最初是爲電話應用開發的(在IP上傳輸SS7),但是也可以用於其他的應用。

UDP(IP協議號17)是一個無連結的數據報協議。它是一個“best effort”或者“不可靠”協議——不是因爲它特別不可靠,而是因爲它不檢查數據包是否已經到達目的地,並且不保證它們按順序到達。如果一個應用程序需要這些特點,它必須自己提供或者使用TCP

UDP的典型性應用是如流媒體(音頻和視頻等)這樣按時到達比可靠性更重要的應用,或者如DNS查找這樣的簡單查詢/響應應用,如果建立可靠的連結所作的額外工作將是不成比例地大。

DCCP目前正由IEFT開發。它提供TCP流動控制語義,但對於用戶來說保留了UDP的數據報服務模型。

TCP和UDP都用來支持一些高層的應用。任何給定網絡地址的應用通過它們的TCP或者UDP端口號區分。根據慣例使一些大衆所知的端口與特定的應用相聯繫。

RTP是爲如音頻和視頻流這樣的實時數據設計的數據報協議。RTP是使用UDP包格式作爲基礎的會話層,然而據說它位於因特網協議棧的傳輸層。

網絡互連層

正如最初所定義的,網絡層解決在一個單一網絡上傳輸數據包的問題。類似的協議有X.25ARPANETHost/IMP Protocol

隨着因特網思想的出現,在這個層上添加了附加的功能,也就是將數據從源網絡傳輸到目的網絡。這就牽涉到在網絡組成的網上選擇路徑將數據包傳輸,也就是因特網

在因特網協議組中,IP完成數據從源發送到目的基本任務。IP能夠承載多種不同的高層協議的數據;這些協議使用一個唯一的IP協議號進行標識。ICMP和IGMP分別是1和2。

一些IP承載的協議,如ICMP(用來發送關於IP發送的診斷信息)和IGMP(用來管理多播數據),它們位於IP層之上但是完成網絡層的功能,這表明了因特網和OSI模型之間的不兼容性。所有的路由協議,如BGP、 OSPF、和RIP實際上也是網絡層的一部分,儘管似乎它們應該屬於更高的協議棧。

網絡接口層

網絡接口層實際上並不是因特網協議組中的一部分,但是它是數據包從一個設備的網絡層傳輸到另外一個設備的網絡層的方法。這個過程能夠在網卡軟件驅動程序中控制,也可以在韌體或者專用芯片中控制。這將完成如添加報頭準備發送、通過物理媒介實際發送這樣一些數據鏈路功能。另一端,鏈路層將完成數據幀接收、去除報頭並且將接收到的包傳到網絡層。

然而,鏈路層並不經常這樣簡單。它也可能是一個虛擬專有網絡(VPN)或者隧道,在這裏從網絡層來的包使用隧道協議和其他(或者同樣的)協議組發送而不是發送到物理的接口上。VPN和隧道通常預先建好,並且它們有一些直接發送到物理接口所沒有的特殊特點(例如,它可以加密經過它的數據)。由於現在鏈路“層”是一個完整的網絡,這種協議組的遞歸使用可能引起混淆。但是它是一個實現常見覆雜功能的一個優秀方法。(儘管需要注意預防一個已經封裝並且經隧道發送下去的數據包進行再次地封裝和發送)。


TCP三次握手四次揮手詳解


1、建立連接協議(三次握手)

(1)客戶端發送一個帶SYN標誌的TCP報文到服務器。這是三次握手過程中的報文1。
(2) 服務器端迴應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ACK標誌和SYN標誌。因此它表示對剛纔客戶端SYN報文的迴應;同時又標誌SYN給客戶端,詢問客戶端是否準備好進行數據通訊。
(3) 客戶必須再次迴應服務段一個ACK報文,這是報文段3。
2、連接終止協議(四次揮手)
   由於TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP連接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
 (1) TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送(報文段4)。
 (2) 服務器收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1(報文段5)。和SYN一樣,一個FIN將佔用一個序號。
 (3) 服務器關閉客戶端的連接,發送一個FIN給客戶端(報文段6)。
 (4) 客戶段發回ACK報文確認,並將確認序號設置爲收到序號加1(報文段7)。
CLOSED: 這個沒什麼好說的了,表示初始狀態。
LISTEN: 這個也是非常容易理解的一個狀態,表示服務器端的某個SOCKET處於監聽狀態,可以接受連接了。
SYN_RCVD: 這個狀態表示接受到了SYN報文,在正常情況下,這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一箇中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最後一個ACK報文不予發送。因此這種狀態時,當收到客戶端的ACK報文後,它會進入到ESTABLISHED狀態。
SYN_SENT: 這個狀態與SYN_RCVD遙想呼應,當客戶端SOCKET執行CONNECT連接時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
ESTABLISHED:這個容易理解了,表示連接已經建立了。
FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。
FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你,稍後再關閉連接。
TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。
CLOSING: 這種狀態比較特殊,實際情況中應該是很少見,屬於一種比較罕見的例外狀態。正常情況下,當你發送FIN報文後,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態表示你發送FIN報文後,並沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那麼就出現了雙方同時發送FIN報文的情況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET連接。
CLOSE_WAIT: 這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那麼你也就可以close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。
LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。
最後有2個問題的回答,我自己分析後的結論(不一定保證100%正確)
1、 爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?
這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。
2、 爲什麼TIME_WAIT狀態還需要等2MSL後才能返回到CLOSED狀態?
這是因爲:雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到ESTABLISH狀態那樣);但是因爲我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK報文會一定被對方收到,因此對方處於LAST_ACK狀態下的SOCKET可能會因爲超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的ACK報文。

新:

1. TCP的三次握手最主要是防止已過期的連接再次傳到被連接的主機。(廢棄連接問題)
    如果採用兩次的話,會出現下面這種情況。比如是A機要連到B機,結果發送的連接信息由於某種原因沒有到達B機;
於是,A機又發了一次,結果這次B收到了,於是就發信息回來,兩機就連接。傳完東西后,斷開。結果這時候,原先沒有到達的連接信息突然又傳到了B機,於是B機發信息給A,然後B機就以爲和A連上了,這個時候B機就在等待A傳東西過去。

2. 三次握手改成僅需要兩次握手,死鎖是可能發生
    考慮計算機A和B之間的通信,假定B給A發送一個連接請求分組,A收到了這個分組,併發送了確認應答分組。按照兩次握手的協定,A認爲連接已經成功地建立了,可以開始發送數據分組。可是,B在A的應答分組在傳輸中被丟失的情況下,將不知道A是否已準備好,不知道A建議什麼樣的序列號,B甚至懷疑A是否收到自己的連接請求分組。在這種情況下,B認爲連接還未建立成功,將忽略A發來的任何數據分組,只等待連接確認應答分組。而A在發出的分組超時後,重複發送同樣的分組。這樣就形成了死鎖

3. TCP通訊中,select到讀事件,但是讀到的數據量是0,爲什麼,如何解決????
    select 返回0代表超時。select出錯返回-1。
    select到讀事件,但是讀到的數據量爲0,說明對方已經關閉了socket的讀端。本端關閉讀即可。
    當select出錯時,會將接口置爲可讀又可寫。這時就要通過判斷select的返回值爲-1來區分。

4. 2MSL(maximum segment lifetime) 
    (1).等待一段時間,防止最後的FIN的ACK包丟失,對方未收到ACK會重發FIN
    (2).TCP連接在2MSL時間內 ip,port不能重新被bind

5.復位報文(RST)
(1).接收到不存在端口的連接請求,回覆RST包(但是udp是響應ICMP端口不可達的error)
(2).異常終止一個連接,發送RST包,收到RST的一方終止該連接。
(3).收到一個半開連接的數據包後,回覆RST,收到RST的一方終止該連接。

6.幾種情況
(1).服務器未開啓服務,回覆RST
(2).服務器連接正常關閉,回覆FIN
(3).服務器進程異常終止,回覆RST。
(4).服務器直接掉電,如果客戶端沒有"發送數據"或者"設置keepalive選項",客戶端將一直保持此半開連接。
    如果客戶端重新連接,將新建立一個連接。
(5).服務器重啓時,如果收到一個半開連接的數據包,回覆RST.


  • 常見面試題
    • TCP協議和UDP協議的區別是什麼
      • TCP協議是有連接的,有連接的意思是開始傳輸實際數據之前TCP的客戶端和服務器端必須通過三次握手建立連接,會話結束之後也要結束連接。而UDP是無連接的
      • TCP協議保證數據按序發送,按序到達,提供超時重傳來保證可靠性,但是UDP不保證按序到達,甚至不保證到達,只是努力交付,即便是按序發送的序列,也不保證按序送到。
      • TCP協議所需資源多,TCP首部需20個字節(不算可選項),UDP首部字段只需8個字節。
      • TCP有流量控制和擁塞控制,UDP沒有,網絡擁堵不會影響發送端的發送速率
      • TCP是一對一的連接,而UDP則可以支持一對一,多對多,一對多的通信。
      • TCP面向的是字節流的服務,UDP面向的是報文的服務。
      • TCP介紹和UDP介紹
    • 請詳細介紹一下TCP協議建立連接和終止連接的過程?
      • 助於理解的一段話
      • 建立一個TCP連接時,會發生下述情形:

      • 1、服務器端必須做好準備接受外來的連接。這通常通過 socket(), bind(), listen() 三個函數來完成的。我們稱之爲 被動打開(passive open).


        2、客戶端通過調用connect發起主動打開(active open)。這導致客戶端TCP發送SYN同步分節。它告訴服務器客戶端在(待建立的)連接中發送的數據的初始化序列號。通用SYN分節不攜帶數據,
        3、服務器必須確認(ACK) 客戶端的SYN,同時自己也得發送一個SYN分節,它含有服務器將在統一連接中發送的數據的初始化序號。服務器在單個分節中發送SYN和對客戶端SYN的ACK確認。
        4、客戶端必須確認服務器的SYN。

        TCP連接的終止:
        1、某個應用程序首先調用close,主動關閉(active close) 該端的TCP於是發送一個FIN分節,表示數據發送完畢。
        2、接收到這個FIN的對端執行被動關閉(passive close)。這個FIN是TCP確認。它的接收也作爲一個文件結束符(end of file) 傳遞給接收端的應用程序(放在排隊等候應用進程接收的任何其他數據之後),因爲FIN的接收意味着接收端應用程序在相應連接上再無額外數據可以接收。
        3、一段時間以後,接收到這個文件結束符的應用進程將調用close關閉它的套接字。這導致它的TCP也發送一個FIN。
        4、接收這個最終FINd額原發送端TCP(即執行主動關閉的一端)確認這個FIN
      • 兩幅圖(來源):
        • 建立連接:三次握手
        • image
        • 關閉連接:四次揮手
        • image
    • 三次握手建立連接時,發送方再次發送確認的必要性?
      • 主要是爲了防止已失效的連接請求報文段突然又傳到了B,因而產生錯誤。假定出現一種異常情況,即A發出的第一個連接請求報文段並沒有丟失,而是在某些網絡結點長時間滯留了,一直延遲到連接釋放以後的某個時間纔到達B,本來這是一個早已失效的報文段。但B收到此失效的連接請求報文段後,就誤認爲是A又發出一次新的連接請求,於是就向A發出確認報文段,同意建立連接。假定不採用三次握手,那麼只要B發出確認,新的連接就建立了,這樣一直等待A發來數據,B的許多資源就這樣白白浪費了。
    • 四次揮手釋放連接時,等待2MSL的意義?
      • 第一,爲了保證A發送的最有一個ACK報文段能夠到達B。這個ACK報文段有可能丟失,因而使處在LAST-ACK狀態的B收不到對已發送的FIN和ACK報文段的確認。B會超時重傳這個FIN和ACK報文段,而A就能在2MSL時間內收到這個重傳的ACK+FIN報文段。接着A重傳一次確認。
      • 第二,就是防止上面提到的已失效的連接請求報文段出現在本連接中,A在發送完最有一個ACK報文段後,再經過2MSL,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。

 

    • 常見的應用中有哪些是應用TCP協議的,哪些又是應用UDP協議的,爲什麼它們被如此設計?
      • 以下應用一般或必須用udp實現?
        • 多播的信息一定要用udp實現,因爲tcp只支持一對一通信。
        • 如果一個應用場景中大多是簡短的信息,適合用udp實現,因爲udp是基於報文段的,它直接對上層應用的數據封裝成報文段,然後丟在網絡中,如果信息量太大,會在鏈路層中被分片,影響傳輸效率。
        • 如果一個應用場景重性能甚於重完整性和安全性,那麼適合於udp,比如多媒體應用,缺一兩幀不影響用戶體驗,但是需要流媒體到達的速度快,因此比較適合用udp
        • 如果要求快速響應,那麼udp聽起來比較合適
        • 如果又要利用udp的快速響應優點,又想可靠傳輸,那麼只能考上層應用自己制定規則了。
        • 常見的使用udp的例子:ICQ,QQ的聊天模塊。
      • 以qq爲例的一個說明(轉載自知乎

        登陸採用TCP協議和HTTP協議,你和好友之間發送消息,主要採用UDP協議,內網傳文件採用了P2P技術。總來的說: 
        1.登陸過程,客戶端client 採用TCP協議向服務器server發送信息,HTTP協議下載信息。登陸之後,會有一個TCP連接來保持在線狀態。 
        2.和好友發消息,客戶端client採用UDP協議,但是需要通過服務器轉發。騰訊爲了確保傳輸消息的可靠,採用上層協議來保證可靠傳輸。如果消息發送失敗,客戶端會提示消息發送失敗,並可重新發送。 
        3.如果是在內網裏面的兩個客戶端傳文件,QQ採用的是P2P技術,不需要服務器中轉。

        image

發佈了20 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章