TCP之种种连接异常
1. connect出錯(cuò):
(1) 若TCP客戶端沒有收到syn分節(jié)的響應(yīng),則返回ETIMEOUT錯(cuò)誤;調(diào)用connect函數(shù)時(shí),內(nèi)核發(fā)送一個(gè)syn,若無響應(yīng)則等待6s后再發(fā)送一個(gè),若仍然無響應(yīng)則等待24s后在發(fā)送一個(gè),若總共等待75s后仍未收到響應(yīng)則返回本錯(cuò)誤;
(2) 若對(duì)客戶的syn響應(yīng)是rst,則表明該服務(wù)器在我們指定的端口上沒有進(jìn)程在等待與之連接,這是一種硬錯(cuò)誤,客戶一收到rst馬上返回ECONNREFUSED錯(cuò)誤;
(3) 若客戶發(fā)送的syn在中間的某個(gè)路由器上引發(fā)了目的不可達(dá)icmp錯(cuò)誤,則認(rèn)為是一種軟錯(cuò)誤。客戶主機(jī)內(nèi)核保存該消息,并按照第一種情況的時(shí)間間隔繼續(xù)發(fā)送syn,咋某個(gè)規(guī)定時(shí)間后仍未收到響應(yīng),則把保存的消息作為EHOSTUNREACH或者ENETUNREACH錯(cuò)誤返回給進(jìn)程;
2. accept返回前連接中止:
在比較忙的服務(wù)器中,在建立三次握手之后,調(diào)用accept之前,可能出現(xiàn)客戶端斷開連接的情況;如,三次握手之后,客戶端發(fā)送rst,然后服務(wù)器調(diào)用accept。posix指出這種情況errno設(shè)置為CONNABORTED;
注意Berkeley實(shí)現(xiàn)中,沒有返回這個(gè)錯(cuò)誤,而是EPROTO,同時(shí)完成三次握手的連接會(huì)從已完成隊(duì)列中移除;在這種情況下,如果我們用select監(jiān)聽到有新的連接完成,但之后又被從完成隊(duì)列中刪除,此時(shí)如果調(diào)用阻塞accept就會(huì)產(chǎn)生阻塞;
解決辦法:
(1) 使用select監(jiān)聽套接字是否有完成連接的時(shí)候,總是把這個(gè)監(jiān)聽套接字設(shè)置為非阻塞;
(2) 在后續(xù)的accept調(diào)用中忽略以下錯(cuò)誤,EWOULDBLOCK(Berkeley實(shí)現(xiàn),客戶中止連接), ECONNABORTED(posix實(shí)現(xiàn),客戶中止連接), EPROTO(serv4實(shí)現(xiàn),客戶中止連接)和EINTR(如果有信號(hào)被捕獲);
3.服務(wù)器進(jìn)程終止(崩潰):
在客戶端和服務(wù)器端建立連接之后,使用kill命令殺死服務(wù)器進(jìn)程,進(jìn)程終止會(huì)關(guān)閉所有打開的描述符,這導(dǎo)致了其向客戶端發(fā)送了一個(gè)FIN,而客戶端則響應(yīng)了一個(gè)ack,這就完成了tcp連接終止的前半部分,只代表服務(wù)器不在發(fā)送數(shù)據(jù)了;但是客戶端并不知道服務(wù)器端已經(jīng)終止了,當(dāng)客戶端向服務(wù)器寫數(shù)據(jù)的時(shí)候,由于服務(wù)器進(jìn)程終止,所以響應(yīng)了rst,如果我們使用select等方式,能夠立即知道當(dāng)前連接狀態(tài);如下:
(1) 如果對(duì)端tcp發(fā)送數(shù)據(jù),那么套接字可讀,并且read返回一個(gè)大于0的值(讀入字節(jié)數(shù));
(2) 如果對(duì)端tcp發(fā)送了fin(對(duì)端進(jìn)程終止),那么該套接字變?yōu)榭勺x,并且read返回0(EOF);
(3) 如果對(duì)端tcp發(fā)送rst(對(duì)端主機(jī)崩潰并重啟),那么該套接字變?yōu)榭勺x,并且read返回-1,errno中含有確切錯(cuò)誤碼;
4. sigpipe信號(hào):
當(dāng)一個(gè)進(jìn)程向某個(gè)收到rst的套接字執(zhí)行寫操作的時(shí)候,內(nèi)核向該進(jìn)程發(fā)送一個(gè)SIGPIPE信號(hào),該信號(hào)的默認(rèn)行為是終止進(jìn)程,因此進(jìn)程必須捕獲它以免不情愿的被終止;
不論進(jìn)程是捕捉了該信號(hào)并從信號(hào)處理函數(shù)中返回,還是簡單忽略該信號(hào),寫操作都講返回EPIPE錯(cuò)誤;
5. 服務(wù)器主機(jī)崩潰:
建立連接之后,服務(wù)器主機(jī)崩潰,此時(shí)如果客戶端發(fā)送數(shù)據(jù),會(huì)發(fā)現(xiàn)客戶端會(huì)在一定時(shí)間內(nèi)持續(xù)重傳,視圖從服務(wù)器端收到數(shù)據(jù)的ack,當(dāng)重傳時(shí)間超過指定時(shí)間后,服務(wù)器仍然沒有響應(yīng),那么返回的是ETIMEDOUT;
6. 服務(wù)器主機(jī)不可達(dá):
建立連接之后,服務(wù)器主機(jī)未崩潰,但是由于中間路由器故障燈,判定主機(jī)或網(wǎng)絡(luò)不可達(dá),此時(shí)如果客戶端發(fā)送數(shù)據(jù),會(huì)發(fā)現(xiàn)客戶端會(huì)在一定時(shí)間內(nèi)持續(xù)重傳,視圖從服務(wù)器端收到數(shù)據(jù)的ack,當(dāng)重傳時(shí)間超過指定時(shí)間后,服務(wù)器仍然沒有響應(yīng),那么返回的是EHOSTUNREACH或ENETUNREACH;
7. 服務(wù)器主機(jī)崩潰后重啟:
當(dāng)服務(wù)器主機(jī)崩潰重啟后,之前所有的tcp連接丟失,此時(shí)服務(wù)器若收到來自客戶端的數(shù)據(jù),會(huì)響應(yīng)一個(gè)rst;客戶端調(diào)用read將返回一個(gè)ECONNRESET錯(cuò)誤;
8. 服務(wù)器主機(jī)關(guān)機(jī):
系統(tǒng)關(guān)機(jī)時(shí),init進(jìn)程給所有進(jìn)程發(fā)送SIGTERM信號(hào),等待固定的時(shí)間,然后給所有仍在運(yùn)行的進(jìn)程發(fā)送SIGKILL信號(hào),我們的進(jìn)程會(huì)被SIGTERM或者SIGKILL信號(hào)終止,所以與前面服務(wù)器進(jìn)程終止相同,進(jìn)程關(guān)閉所有描述符,并發(fā)送fin,完成服務(wù)器端的半關(guān)閉;
轉(zhuǎn)自:http://www.cnblogs.com/wanpengcoder/p/5356776.html
總結(jié)
以上是生活随笔為你收集整理的TCP之种种连接异常的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 招商证券开户佣金多少
- 下一篇: 2018年全年资料大全 六合彩资料大全