第六章: ICMP:Internet控制報文協(xié)議

6.1 引言

ICMP經(jīng)常被認(rèn)為是IP層的一個組成部分。它傳遞差錯報文以及其他需要注意的信息。ICMP報文通常被IP層或更高層協(xié)議(TCP或UDP)使用。一些ICMP報文把差錯報文返回給用戶進(jìn)程。

ICMP報文是在IP數(shù)據(jù)報內(nèi)部被傳輸?shù)模鐖D6-1所示。


圖6-1 ICMP封裝在IP數(shù)據(jù)報內(nèi)部

ICMP的正式規(guī)范參見RFC 792[Posterl 1981b]。

ICMP報文的格式如圖6-2所示。所有報文的前4個字節(jié)都是一樣的,但是剩下的其他字節(jié)則互不相同。下面我們將逐個介紹各種報文格式。

類型字段可以有15個不同的值,以描述特定類型的ICMP報文。某些ICMP報文還使用代碼字段的值來進(jìn)一步描述不同的條件。

檢驗和字段覆蓋整個ICMP報文。使用的算法與我們在3.2節(jié)中介紹的IP首部檢驗和算法相同。ICMP的檢驗和是必需的。

圖6-2 ICMP報文

在本章中,我們將一般地討論ICMP報文,并對其中一部分作詳細(xì)介紹:地址掩碼請求和應(yīng)答、時間戳請求和應(yīng)答以及不可達(dá)端口。我們將詳細(xì)介紹第27章Ping程序所使用的回應(yīng)請求和應(yīng)答報文和第9章處理IP路由的ICMP報文。

6.2 ICMP報文的類型

各種類型的ICMP報文如圖6-3所示,不同類型由報文中的類型字段和代碼字段來共同決定。

圖中的最后兩列表明ICMP報文是一份查詢報文還是一份差錯報文。因為對ICMP差錯報文有時需要作特殊處理,因此我們需要對它們進(jìn)行區(qū)分。例如,在對ICMP差錯報文進(jìn)行響應(yīng)時,永遠(yuǎn)不會生成另一份ICMP差錯報文(如果沒有這個限制規(guī)則,可能會遇到一個差錯產(chǎn)生另一個差錯的情況,而差錯再產(chǎn)生差錯,這樣會無休止地循環(huán)下去)。

當(dāng)發(fā)送一份ICMP差錯報文時,報文始終包含IP的首部和產(chǎn)生ICMP差錯報文的IP數(shù)據(jù)報的前8個字節(jié)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協(xié)議(根據(jù)IP數(shù)據(jù)報首部中的協(xié)議字段來判斷)和用戶進(jìn)程(根據(jù)包含在IP數(shù)據(jù)報前8個字節(jié)中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯(lián)系起來。6.5節(jié)將舉例來說明一點。


圖6-3 ICMP報文類型

下面各種情況都不會導(dǎo)致產(chǎn)生ICMP差錯報文:

1:ICMP差錯報文(但是,ICMP查詢報文可能會產(chǎn)生ICMP差錯報文)。

2:目的地址是廣播地址(見圖3-9)或多播地址(D類地址,見圖1-5)的IP數(shù)據(jù)報。

3:作為鏈路層廣播的數(shù)據(jù)報。

4:不是IP分片的第一片(將在11.5節(jié)介紹分片)。

5:源地址不是單個主機的數(shù)據(jù)報。這就是說,源地址不能為零地址、環(huán)回地址、廣播地址或多播地址。

這些規(guī)則是為了防止過去允許ICMP差錯報文對廣播分組響應(yīng)所帶來的廣播風(fēng)暴。

6.3 ICMP地址掩碼請求與應(yīng)答

ICMP地址掩碼請求用于無盤系統(tǒng)在引導(dǎo)過程中獲取自己的子網(wǎng)掩碼(3.5節(jié))。系統(tǒng)廣播它的ICMP請求報文(這一過程與無盤系統(tǒng)在引導(dǎo)過程中用RARP獲取IP地址是類似的)。無盤系統(tǒng)獲取子網(wǎng)掩碼的另一個方法是BOOTP協(xié)議,我們將在第16章中介紹。ICMP地址掩碼請求和應(yīng)答報文的格式如圖6-4所示。


圖6-4 ICMP地址掩碼請求和應(yīng)答報文

ICMP報文中的標(biāo)識符和序列號字段由發(fā)送端任意選擇設(shè)定,這些值在應(yīng)答中將被返回。這樣,發(fā)送端就可以把應(yīng)答與請求進(jìn)行匹配。

我們可以寫一個簡單的程序(取名為icmpaddrmask),它發(fā)送一份ICMP地址掩碼請求報文,然后打印出所有的應(yīng)答。由于一般是把請求報文發(fā)往廣播地址,因此這里我們也這樣做。目的地址(140.252.13.63)是子網(wǎng)140.252.13.32的廣播地址(見圖3-12)。

sun % icmpaddrmask 140.252.13.63

received mask = ffffffe0, from 140.252.13.33 來自本機

received mask = ffffffe0, from 140.252.13.35 來自bsdi

received mask = ffff0000, from 140.252.13.34 來自svr4

在輸出中我們首先注意到的是,從svr4返回的子網(wǎng)掩碼是錯的。顯然,盡管svr4接口已經(jīng)設(shè)置了正確的子網(wǎng)掩碼,但是SVR4還是返回了一個普通的B類地址掩碼,就好像子網(wǎng)并不存在一樣。

svr4 % ifconfig emd0

emd0: flags=23<UP,BROADCAST,NOTRAILERS>

inet 140.252.13.34 netmask ffffffe0 broadcast 140.252.13.63

SVR4處理ICMP地址掩碼請求過程存在差錯。

我們用tcpdump命令來查看主機bsdi上的情況,輸出如圖6-5所示。我們用-e選項來查看硬件地址。


圖6-5 發(fā)到廣播地址的ICMP地址掩碼請求

注意,盡管在線路上什么也看不見,但是發(fā)送主機sun也能接收到ICMP應(yīng)答(帶有上面“來自本機”的輸出行)。這是廣播的一般特性:發(fā)送主機也能通過某種內(nèi)部環(huán)回機制收到一份廣播報文拷貝。由于術(shù)語“廣播”的定義是指局域網(wǎng)上的所有主機,因此它必須包括發(fā)送主機在內(nèi)(參見圖2-4,當(dāng)以太網(wǎng)驅(qū)動程序識別出目的地址是廣播地址后,它就把分組送到網(wǎng)絡(luò)上,同時傳一份拷貝到環(huán)回接口)。

接下來,bsdi廣播應(yīng)答,而svr4卻只把應(yīng)答傳給請求主機。通常,應(yīng)答地址必須是單播地址,除非請求端的源IP地址是0.0.0.0。本例不屬于這種情況,因此,把應(yīng)答發(fā)送到廣播地址是BSD/386的一個內(nèi)部差錯。

    RFC規(guī)定,除非系統(tǒng)是地址掩碼的授權(quán)代理,否則它不能發(fā)送地址掩碼應(yīng)答(為了成為授權(quán)代理,它必須進(jìn)行特殊配置,以發(fā)送這些應(yīng)答。參見附錄E)。但是,正如我們從本例中看到的那樣,大多數(shù)主機在收到請求時都發(fā)送一個應(yīng)答,甚至有一些主機還發(fā)送差錯的應(yīng)答。

最后一點可以通過下面的例子來說明。我們向本機IP地址和環(huán)回地址分別發(fā)送地址掩碼請求:

sun % icmpaddrmask sun

received mask = ff000000, from 140.252.13.33

sun %icmpaddrmask localhost

received mask = ff000000, from 127.0.0.1

上述兩種情況下返回的地址掩碼對應(yīng)的都是環(huán)回地址,即A類地址127.0.0.1。還有,我們從圖2-4可以看到,發(fā)送給本機IP地址的數(shù)據(jù)報(140.252.12.33)實際上是送到環(huán)回接口。ICMP地址掩碼應(yīng)答必須是收到請求接口的子網(wǎng)掩碼(這是因為多接口主機每個接口有不同的子網(wǎng)掩碼),因此兩種情況下地址掩碼請求都來自于環(huán)回接口。

6.4 ICMP時間戳請求與應(yīng)答

ICMP時間戳請求允許系統(tǒng)向另一個系統(tǒng)查詢當(dāng)前的時間。返回的建議值是自午夜開始計算的毫秒數(shù),協(xié)調(diào)的統(tǒng)一時間(Coordinated Universal Time,UTC)(早期的參考手冊認(rèn)為UTC是格林尼治時間)。這種ICMP報文的好處是它提供了毫秒級的分辨率,而利用其他方法從別的主機獲取的時間(如某些Unix系統(tǒng)提供的rdate命令)只能提供秒級的分辨率。由于返回的時間是從午夜開始計算的,因此調(diào)用者必須通過其他方法獲知當(dāng)時的日期,這是它的一個缺陷。

ICMP時間戳請求和應(yīng)答報文格式如圖6-6所示。

圖6-6 ICMP時間戳請求和應(yīng)答報文

請求端填寫發(fā)起時間戳,然后發(fā)送報文。應(yīng)答系統(tǒng)收到請求報文時填寫接收時間戳,在發(fā)送應(yīng)答時填寫發(fā)送時間戳。但是,實際上,大多數(shù)的實現(xiàn)把后面兩個字段都設(shè)成相同的值(提供三個字段的原因是可以讓發(fā)送方分別計算發(fā)送請求的時間和發(fā)送應(yīng)答的時間)。

6.4.1 舉例

我們可以寫一個簡單程序(取名為icmptime),給某個主機發(fā)送ICMP時間戳請求,并打印出返回的應(yīng)答。它在我們的小互聯(lián)網(wǎng)上運行結(jié)果如下:

程序打印出ICMP報文中的三個時間戳:發(fā)起時間戳(orig)、接收時間戳(recv)以及發(fā)送時間戳(xmit)。正如我們在這個例子以及下面的例子中所看到的那樣,所有的主機把接收時間戳和發(fā)送時間戳都設(shè)成相同的值。

我們還能計算出往返時間(rtt),它的值是收到應(yīng)答時的時間值減去發(fā)送請求時的時間值。difference的值是接收時間戳值減去發(fā)起時間戳值。這些值之間的關(guān)系如圖6-7所示。

圖6-7icmptime程序輸出的值之間的關(guān)系

如果我們相信RTT的值,并且相信RTT的一半用于請求報文的傳輸,另一半用于應(yīng)答報文的傳輸,那么為了使本機時鐘與查詢主機的時鐘一致,本機時鐘需要進(jìn)行調(diào)整,調(diào)整值是difference減去RTT的一半。在前面的例子中,bsdi的時鐘比sun的時鐘要慢7ms和8ms。

由于時間戳的值是自午夜開始計算的毫秒數(shù),即UTC,因此它們的值始終小于86 400 000 (24×60×60×1000)。這些例子都是在下午4:00以前運行的,并且在一個比UTC慢7個小時的時區(qū),因此它們的值比82 800 000(2300小時)要大是有道理的。

如果對主機bsdi重復(fù)運行該程序數(shù)次,我們發(fā)現(xiàn)接收時間戳和發(fā)送時間戳的最后一位數(shù)總是0。這是因為該版本的軟件(0.9.4版)只能提供10ms的時間分辨率(說明參見附錄B)。

如果對主機svr4運行該程序兩次,我們發(fā)現(xiàn)SVR4時間戳的最后三位數(shù)始終為0:



由于某種原因,SVR4在ICMP時間戳中不提供毫秒級的分辨率。這樣,對秒以下的時間差調(diào)整將不起任何作用。

如果我們對子網(wǎng)140.252.1上的其他主機運行該程序,結(jié)果表明其中一臺主機的時鐘與sun相差3.7秒,而另一個主機時鐘相差近75秒:

另一個令人感興趣的例子是路由器gateway(一個Cisco路由器)。它表明,當(dāng)系統(tǒng)返回一個非標(biāo)準(zhǔn)時間戳值時(不是自午夜開始計算的毫秒數(shù),UTC),它就用32 bit時間戳中的高位來表示。我們的程序證明了一點,在尖括號中打印出了接收和發(fā)送的時間戳值(在關(guān)閉高位之后)。另外,不能計算發(fā)起時間戳和接收時間戳之間的時間差,因為它們的單位不一致。


如果我們在這臺主機上運行該程序數(shù)次,會發(fā)現(xiàn)時間戳值顯然具有毫秒級的分辨率,而且是從某個起始點開始計算的毫秒數(shù),但是起始點并不是午夜UTC(例如,可能是從路由器引導(dǎo)時開始計數(shù)的毫秒數(shù))。

作為最后一個例子,我們來比較sun主機和另一個已知是準(zhǔn)確的系統(tǒng)時鐘——一個NTP stratum 1服務(wù)器(下面我們會更多地討論NTP,網(wǎng)絡(luò)時間協(xié)議)。


如果我們把difference的值減去RTT的一半,結(jié)果表明sun主機上的時鐘要快38.5~51.5ms。

6.4.2 另一種方法

還可以用另一種方法來獲得時間和日期。

1:在1.12節(jié)中描述了日期服務(wù)程序和時間服務(wù)程序。前者是以人們可讀的格式返回當(dāng)前的時間和日期,是一行ASCII字符??梢杂胻elnet命令來驗證這個服務(wù):

另一方面,時間服務(wù)程序返回的是一個32bit的二制進(jìn)數(shù)值,表示自UTC,1900年1月1日午夜起算的秒數(shù)。這個程序是以秒為單位提供的日期和時間(前面我們提過的rdate命令使用的是TCP時間服務(wù)程序)。

2:嚴(yán)格的計時器使用網(wǎng)絡(luò)時間協(xié)議(NTP),該協(xié)議在RFC 1305中給出了描述[Mills1992]。這個協(xié)議采用先進(jìn)的技術(shù)來保證LAN或WA N上的一組系統(tǒng)的時鐘誤差在毫秒級以內(nèi)。對計算機精確時間感興趣的讀者應(yīng)該閱讀這份RFC文檔。

3:開放軟件基金會(OSF)的分布式計算環(huán)境(DCE)定義了分布式時間服務(wù)(DTS),它也提供計算機之間的時鐘同步。文獻(xiàn)[Rosenberg, Kenney and Fisher 1992]提供了該服務(wù)的其他細(xì)節(jié)描述。

4:伯克利大學(xué)的Unix系統(tǒng)提供守護(hù)程序timed(8),來同步局域網(wǎng)上的系統(tǒng)時鐘。不像NTP和DTS,timed不在廣域網(wǎng)范圍內(nèi)工作。

6.5 ICMP端口不可達(dá)差錯

最后兩小節(jié)我們來討論ICMP查詢報文—地址掩碼和時間戳查詢及應(yīng)答?,F(xiàn)在來分析一種ICMP差錯報文,即端口不可達(dá)報文,它是ICMP目的不可到達(dá)報文中的一種,以此來看一看ICMP差錯報文中所附加的信息。使用UDP(見第11章)來查看它。

UDP的規(guī)則之一是,如果收到一份UDP數(shù)據(jù)報而目的端口與某個正在使用的進(jìn)程不相符,那么UDP返回一個ICMP不可達(dá)報文。可以用TFTP來強制生成一個端口不可達(dá)報文(TFTP將在第15章描述)。

對于TFTP服務(wù)器來說,UDP的公共端口號是69。但是大多數(shù)的TFTP客戶程序允許用connect命令來指定一個不同的端口號。這里,我們就用它來指定8888端口:


connect命令首先指定要連接的主機名及其端口號,接著用get命令來取文件。敲入get命令后,一份UDP數(shù)據(jù)報就發(fā)送到主機svr4上的8888端口。tcpdump命令引起的報文交換結(jié)果如圖6-8所示。


圖6-8 由TFTP產(chǎn)生的ICMP端口不可達(dá)差錯

在UDP數(shù)據(jù)報送到svr4之前,要先發(fā)送一份ARP請求來確定它的硬件地址(第1行)。接著返回ARP應(yīng)答(第2行),然后才發(fā)送UDP數(shù)據(jù)報(第3行)(在tcpdump的輸出中保留ARP請求和應(yīng)答是為了提醒我們,這些報文交換可能在第一個IP數(shù)據(jù)報從一個主機發(fā)送到另一個主機之前是必需的。在本書以后的章節(jié)中,如果這些報文與討論的題目不相關(guān),那么我們將省略它們)。

一個ICMP端口不可達(dá)差錯是立刻返回的(第4行)。但是,TFTP客戶程序看上去似乎忽略了這個ICMP報文,而在5秒鐘之后又發(fā)送了另一份UDP數(shù)據(jù)報(第5行)。在客戶程序放棄之前重發(fā)了三次。

注意,ICMP報文是在主機之間交換的,而不用目的端口號,而每個20字節(jié)的UDP數(shù)據(jù)報則是從一個特定端口(2924)發(fā)送到另一個特定端口(8888)。

跟在每個UDP后面的數(shù)字20指的是UDP數(shù)據(jù)報中的數(shù)據(jù)長度。在這個例子中,20字節(jié)包括TFTP的2個字節(jié)的操作代碼,9個字節(jié)以空字符結(jié)束的文件名temp.foo,以及9個字節(jié)以空字符結(jié)束的字符串netascii(TFTP報文的詳細(xì)格式參見圖15-1)。

如果用-e選項運行同樣的例子,我們可以看到每個返回的ICMP端口不可達(dá)報文的完整長度。這里的長度為70字節(jié),各字段分配如圖6-9所示。


圖6-9 “UDP端口不可達(dá)”例子中返回的ICMP報文

ICMP的一個規(guī)則是,ICMP差錯報文(參見圖6-3的最后一列)必須包括生成該差錯報文的數(shù)據(jù)報IP首部(包含任何選項),還必須至少包括跟在該IP首部后面的前8個字節(jié)。在我們的例子中,跟在IP首部后面的前8個字節(jié)包含UDP的首部(見圖11-2)。

一個重要的事實是包含在UDP首部中的內(nèi)容是源端口號和目的端口號。就是由于目的端口號(8888)才導(dǎo)致產(chǎn)生了ICMP端口不可達(dá)的差錯報文。接收ICMP的系統(tǒng)可以根據(jù)源端口號(2924)來把差錯報文與某個特定的用戶進(jìn)程相關(guān)聯(lián)(在本例中是TFTP客戶程序)。

導(dǎo)致差錯的數(shù)據(jù)報中的IP首部要被送回的原因是因為IP首部中包含了協(xié)議字段,使得ICMP可以知道如何解釋后面的8個字節(jié)(在本例中是UDP首部)。如果我們來查看TCP首部(圖17-2),可以發(fā)現(xiàn)源端口和目的端口被包含在TCP首部的前8個字節(jié)中。

ICMP不可達(dá)報文的一般格式如圖6-10所示。


圖6-10 ICMP不可達(dá)報文

在圖6-3中,我們注意到有16種不同類型的ICMP不可達(dá)報文,代碼分別從0到15。ICMP端口不可達(dá)差錯代碼是3。另外,盡管圖6-10指出了在ICMP報文中的第二個32 bit字必須為0,但是當(dāng)代碼為4時(“需要分片但設(shè)置了不分片比特”),路徑MTU發(fā)現(xiàn)機制(2.9節(jié))卻允許路由器把外出接口的MTU填在這個32 bit字的低16 bit中。我們在11.6節(jié)中給出了一個這種差錯的例子。

盡管ICMP規(guī)則允許系統(tǒng)返回多于8個字節(jié)的產(chǎn)生差錯的IP數(shù)據(jù)報中的數(shù)據(jù),但是大多數(shù)從伯克利派生出來的系統(tǒng)只返回8個字節(jié)。Solaris 2.2的ip_icmp_return_data_bytes選項默認(rèn)條件下返回前64個字節(jié)(E.4節(jié))。

tcpdump 時間系列

在本書的后面章節(jié)中,我們還要以時間系列的格式給出tcpdump命令的輸出,如圖6-11所示。

圖6-11 發(fā)送到無效端口的TFTP請求的時間系列

時間隨著向下而遞增,在圖左邊的時間標(biāo)記與tcpdump命令的輸出是相同的(見圖6-8)。位于圖頂部的標(biāo)記是通信雙方的主機名和端口號。需要指出的是,隨著頁面向下的y坐標(biāo)軸與真正的時間值不是成比例的。當(dāng)出現(xiàn)一個有意義的時間段時,在本例中是每5秒之間的重發(fā),我們就在時間系列的兩側(cè)作上標(biāo)記。當(dāng)UDP或TCP數(shù)據(jù)正在被傳送時,我們用粗線的行來表示。

當(dāng)ICMP報文返回時,為什么TFTP客戶程序還要繼續(xù)重發(fā)請求呢?這是由于網(wǎng)絡(luò)編程中的一個因素,即BSD系統(tǒng)不把從插口(socket)接收到的ICMP報文中的UDP數(shù)據(jù)通知用戶進(jìn)程,除非該進(jìn)程已經(jīng)發(fā)送了一個connect命令給該插口。標(biāo)準(zhǔn)的BSD TFTP客戶程序并不發(fā)送connect命令,因此它永遠(yuǎn)也不會收到ICMP差錯報文的通知。

這里需要注意的另一點是TFTP客戶程序所采用的不太好的超時重傳算法。它只是假定5秒是足夠的,因此每隔5秒就重傳一次,總共需要25秒鐘的時間。在后面我們將看到TCP有一個較好的超時重發(fā)算法。

TFTP客戶程序所采用的超時重傳算法已被RFC所禁用。不過,在作者所在子網(wǎng)上的三個系統(tǒng)以及Solaris 2.2仍然在使用它。AIX 3.2.2采用一種指數(shù)退避方法來設(shè)置超時值,分別在0、5、15和35秒時重發(fā)報文,這正是所推薦的方法。我們將在第21章更詳細(xì)地討論超時問題。

最后需要指出的是,ICMP報文是在發(fā)送UDP數(shù)據(jù)報3.5ms后返回的,這與第7章我們所看到的Ping應(yīng)答的往返時間差不多。

6.6 ICMP報文的4.4BSD處理

由于ICMP覆蓋的范圍很廣,從致命差錯到信息差錯,因此即使在一個給定的系統(tǒng)實現(xiàn)中,對每個ICMP報文的處理都是不相同的。圖6-12的內(nèi)容與圖6-3相同,它顯示的是4.4BSD系統(tǒng)對每個可能的ICMP報文的處理方法。

圖6-12 4.4BSD系統(tǒng)對ICMP報文的處理

如果最后一列標(biāo)明是“內(nèi)核”,那么ICMP就由內(nèi)核來處理。如果最后一列指明是“用戶進(jìn)程”,那么報文就被傳送到所有在內(nèi)核中登記的用戶進(jìn)程,以讀取收到的ICMP報文。如果不存在任何這樣的用戶進(jìn)程,那么報文就悄悄地被丟棄(這些用戶進(jìn)程還會收到所有其他類型的ICMP報文的拷貝,雖然它們應(yīng)該由內(nèi)核來處理,當(dāng)然用戶進(jìn)程只有在內(nèi)核處理以后才能收到這些報文)。有一些報文完全被忽略。最后,如果最后一列標(biāo)明的是引號內(nèi)的一串字符,那么它就是對應(yīng)的Unix差錯。其中一些差錯,如TCP對發(fā)送端關(guān)閉的處理等,我們將在以后的章節(jié)中對它們進(jìn)行討論。

6.7 小結(jié)

本章對每個系統(tǒng)都必須包括的Internet控制報文協(xié)議進(jìn)行了討論。圖6-3列出了所有的ICMP報文類型,其中大多數(shù)都將在以后的章節(jié)中加以討論。

我們詳細(xì)討論了ICMP地址掩碼請求和應(yīng)答以及時間戳請求和應(yīng)答。這些是典型的請求—應(yīng)答報文。二者在ICMP報文中都有標(biāo)識符和序列號。發(fā)送端應(yīng)用程序在標(biāo)識字段內(nèi)存入一個唯一的數(shù)值,以區(qū)別于其他進(jìn)程的應(yīng)答。序列號字段使得客戶程序可以在應(yīng)答和請求之間進(jìn)行匹配。

我們還討論了ICMP端口不可達(dá)差錯,一種常見的ICMP差錯。對返回的ICMP差錯信息進(jìn)行了分析:導(dǎo)致差錯的IP數(shù)據(jù)報的首部及后續(xù)8個字節(jié)。這個信息對于ICMP差錯的接收方來說是必要的,可以更多地了解導(dǎo)致差錯的原因。這是因為TCP和UDP都在它們的首部前8個字節(jié)中存入源端口號和目的端口號。

最后,我們第一次給出了按時間先后的tcpdump輸出,這種表示方式在本書后面的章節(jié)中會經(jīng)常用到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容