網(wǎng)絡(luò)協(xié)議那么多续崖,為什么面試喜歡問(wèn)TCP敲街?原因無(wú)外乎兩個(gè):1、TCP協(xié)議直接與進(jìn)程打交道袜刷,寫(xiě)網(wǎng)絡(luò)程序要用聪富;2、TCP協(xié)議設(shè)計(jì)十分精巧著蟹,在一個(gè)不可靠的IP網(wǎng)絡(luò)上實(shí)現(xiàn)了可靠傳輸,因?yàn)榫缮颐В莆誘CP的原理自然也有難度萧豆,對(duì)它掌握如何,很能反映面試者的基礎(chǔ)水平昏名。閑言少敘涮雷,看看這幾個(gè)問(wèn)題你能不能答出來(lái)!
1轻局、A進(jìn)程通過(guò)TCP向另一臺(tái)機(jī)器上的B進(jìn)程發(fā)送了一個(gè)字符串“hello”洪鸭,TCP返回對(duì)方成功接收的確認(rèn)信息样刷,請(qǐng)問(wèn),現(xiàn)在進(jìn)程A是否可以肯定地說(shuō)進(jìn)程B收到了它發(fā)送的字符串览爵?
答案:不能置鼻!舉反例,進(jìn)程B所在機(jī)器的TCP收到進(jìn)程A發(fā)送的“hello”信息后蜓竹,告訴進(jìn)程A發(fā)送成功箕母,但有可能沒(méi)有立即將數(shù)據(jù)交給進(jìn)程B,而是放在自己的緩沖區(qū)中俱济,等待進(jìn)程B讀取嘶是,如果機(jī)器此時(shí)突然掉電,緩沖區(qū)中的信息將丟失蛛碌,進(jìn)程B將不可能收到“hello”字符串聂喇。
2、有什么辦法來(lái)盡量避免上述情況的發(fā)生呢蔚携?
答案:將TCP報(bào)文段首部中的PSH標(biāo)志置1希太,這樣會(huì)讓B端的TCP協(xié)議收到數(shù)據(jù)后盡快交給進(jìn)程B,能不緩存盡量不要緩存浮梢。
3跛十、我們知道通常TCP連接的建立需要3次握手,關(guān)閉需要4次握手秕硝,為什么關(guān)閉會(huì)多一次呢芥映?
答案:簡(jiǎn)單說(shuō),就是TCP允許半關(guān)閉狀態(tài)的存在远豺。當(dāng)進(jìn)程A向進(jìn)程B發(fā)送FIN奈偏,B也向A發(fā)送確認(rèn)后。此時(shí)此刻的狀態(tài)就是半關(guān)閉狀態(tài)躯护,A發(fā)送的FIN就是告訴B:“我要發(fā)送的數(shù)據(jù)都發(fā)送完了”但B沒(méi)有發(fā)送FIN給A惊来,有可能代表B還有沒(méi)發(fā)送完的數(shù)據(jù),如果B也發(fā)送完數(shù)據(jù)了棺滞,B就發(fā)送FIN給進(jìn)程A裁蚁,進(jìn)程A確認(rèn)B發(fā)送的FIN,這時(shí)继准,雙方都已經(jīng)發(fā)送完了數(shù)據(jù)枉证,連接就斷開(kāi)了,TCP回收相關(guān)資源移必。
4室谚、假如服務(wù)器突然掉電重啟揍障,但客戶(hù)端并不知情古沥,請(qǐng)問(wèn)此時(shí)二者之間的TCP連接處于什么狀態(tài)蚓庭?
答案:處于半打開(kāi)狀態(tài)痹愚。就是客戶(hù)端還覺(jué)得連接是正常的,服務(wù)器這邊已經(jīng)沒(méi)有連接的任何信息了入篮。
5陈瘦、那么,假如此時(shí)客戶(hù)端通過(guò)這個(gè)連接向服務(wù)器請(qǐng)求數(shù)據(jù)崎弃,服務(wù)器會(huì)怎么應(yīng)對(duì)呢甘晤?
答案:服務(wù)器收到客戶(hù)端的請(qǐng)求會(huì)進(jìn)行一次ARP查詢(xún),獲得客戶(hù)端MAC地址饲做,然而由于已經(jīng)丟失了所有連接信息线婚,此時(shí)的服務(wù)器是一臉懵逼(就像喝了孟婆湯!)盆均,于是乎塞弊,它會(huì)發(fā)一個(gè)RST給客戶(hù)端,表示:“哥們泪姨,我不認(rèn)識(shí)你游沿,想跟我說(shuō)話請(qǐng)先發(fā)送SYN!”
6肮砾、假如客戶(hù)端按照服務(wù)器的要求重新建立連接诀黍,卻搞錯(cuò)了服務(wù)器的端口號(hào),會(huì)發(fā)生什么情況呢仗处?
答案:有兩種可能眯勾,一種是服務(wù)器端的TCP收到客戶(hù)端請(qǐng)求,查看本機(jī)上是否有進(jìn)程在監(jiān)聽(tīng)相應(yīng)的端口婆誓,如果有吃环,就把請(qǐng)求交給這個(gè)進(jìn)程,一般而言洋幻,這個(gè)進(jìn)程不會(huì)接受這個(gè)連接的郁轻,于是它會(huì)發(fā)一個(gè)RST給客戶(hù)端。還有一種可能是TCP沒(méi)有找到哪個(gè)進(jìn)程在監(jiān)聽(tīng)相應(yīng)的端口文留,于是TCP就會(huì)直接發(fā)一個(gè)RST給客戶(hù)端好唯,一般而言都會(huì)是這種情況。
7燥翅、假如現(xiàn)在有一個(gè)多進(jìn)程服務(wù)器渠啊,服務(wù)器進(jìn)程為A,接受一個(gè)連接后新建一個(gè)進(jìn)程B來(lái)處理連接,再接受一個(gè)連接后又建一個(gè)進(jìn)程C來(lái)處理這個(gè)連接权旷,請(qǐng)問(wèn),進(jìn)程ABC是否監(jiān)聽(tīng)同樣的端口?
答案:是拄氯!
8躲查、那TCP接收到發(fā)送給這個(gè)端口的報(bào)文段,怎么決定發(fā)給哪個(gè)進(jìn)程呢译柏?
答案:首先镣煮,所有的SYN報(bào)文段都會(huì)發(fā)送給服務(wù)器進(jìn)程A,其他的報(bào)文段依據(jù)<sourceIP:port,targetIP:port>這個(gè)四元組來(lái)決定發(fā)送給進(jìn)程B還是進(jìn)程C鄙麦。
9典唇、假如上面的服務(wù)器進(jìn)程A收到一個(gè)連接請(qǐng)求,正在為這個(gè)請(qǐng)求創(chuàng)建處理進(jìn)程的時(shí)候胯府,又有新的連接請(qǐng)求進(jìn)來(lái)了介衔,TCP會(huì)怎么處理呢?
答案:一般情況下骂因,服務(wù)器進(jìn)程A會(huì)給TCP一個(gè)指示炎咖,讓TCP維護(hù)一個(gè)適當(dāng)長(zhǎng)度的連接隊(duì)列,TCP與新連接請(qǐng)求完成三次握手后寒波,就會(huì)把這個(gè)連接放入連接隊(duì)列中乘盼,服務(wù)器進(jìn)程A會(huì)在合適的時(shí)候來(lái)從這個(gè)隊(duì)列中取連接。
10俄烁、這個(gè)連接對(duì)列是否會(huì)對(duì)服務(wù)器的并發(fā)處理能力產(chǎn)生影響呢绸栅?如果會(huì),會(huì)有什么影響页屠?
答案:不會(huì)粹胯!二者沒(méi)有必然關(guān)系。
11卷中、MSS和MTU各是什么矛双,二者是什么關(guān)系?
答案:MSS是TCP最大報(bào)文段長(zhǎng)度蟆豫,就是TCP發(fā)送數(shù)據(jù)需要對(duì)數(shù)據(jù)分段時(shí)议忽,最大的段的字節(jié)數(shù)。MTU是最大傳輸單元十减,通常由網(wǎng)卡的硬件特性規(guī)定栈幸,表示通過(guò)該網(wǎng)卡傳輸?shù)臄?shù)據(jù)單元最大的字節(jié)數(shù)。MSS要受同一臺(tái)機(jī)器上的MTU限制帮辟。比如MTU為1500字節(jié)速址,那么MSS就只能是1460字節(jié),這是因?yàn)?460字節(jié)的數(shù)據(jù)在通過(guò)網(wǎng)卡向外傳輸時(shí)由驹,會(huì)加上20字節(jié)的ip頭和20字節(jié)的tcp頭芍锚。
12、假設(shè)機(jī)器A和B的MSS分別是1400和1600,請(qǐng)問(wèn)并炮,A通過(guò)TCP向B發(fā)送數(shù)據(jù)時(shí)默刚,是否可以發(fā)送長(zhǎng)度為1600字節(jié)的數(shù)據(jù)段?
答案:不可以逃魄,雖然發(fā)送1600字節(jié)的數(shù)據(jù)段沒(méi)有突破B的MSS荤西,但是突破了A自己的MSS。這樣一來(lái)伍俘,當(dāng)這1600字節(jié)的數(shù)據(jù)段通過(guò)A的網(wǎng)卡向B發(fā)送時(shí)邪锌,會(huì)被切分為2個(gè)IP片,每個(gè)為840字節(jié)癌瘾,以保證不突破A的MTU觅丰,這顯然降低了傳輸?shù)男剩驗(yàn)閮蓚€(gè)840字節(jié)中有著相同的IP頭和TCP頭柳弄。
13舶胀、機(jī)器A和B有一條TCP連接,假如A想盡快斷開(kāi)連接碧注,應(yīng)當(dāng)怎么辦嚣伐?
答案:A可以直接給B發(fā)送一個(gè)RST,就可以了萍丐,相當(dāng)于告訴B轩端,我關(guān)閉連接了,你看著辦吧逝变。這叫做異常關(guān)閉基茵。
14、B的TCP收到A發(fā)來(lái)的RST壳影,會(huì)怎么辦拱层?
答案:B的TCP會(huì)告訴上層的進(jìn)程,連接已經(jīng)斷開(kāi)了宴咧,然后就會(huì)回收這條連接的資源根灯,并不會(huì)發(fā)送任何確認(rèn)信息給A。所謂你無(wú)情休怪我不義掺栅。
15烙肺、假設(shè)A正常斷開(kāi)與B的TCP連接,當(dāng)收到B的FIN時(shí)氧卧,A發(fā)送ACK給B桃笙,是否就算完成了4次握手,連接已經(jīng)成功斷開(kāi)沙绝?
答案:不是搏明,A的TCP會(huì)啟動(dòng)一個(gè)定時(shí)器鼠锈,等待2MSL的時(shí)間,這主要是為了防止A的ACK沒(méi)有成功傳到B熏瞄,讓B以為自己的FIN沒(méi)有送到A處脚祟,反復(fù)重傳FIN的問(wèn)題。2MSL的時(shí)間到時(shí)强饮,如果A沒(méi)有再次收到B的FIN,說(shuō)明B成功收到A的ACK为黎,A就可以安全地?cái)嚅_(kāi)這個(gè)連接邮丰,若期間再次收到B的FIN,則A會(huì)重傳ACK铭乾。