阻塞与非阻塞个人小结
?? 1.connect函數(shù)響應(yīng)中斷返回后仍然回到函數(shù)的調(diào)用。
?????? 實踐證明,對于一個非阻塞的socket,如果在調(diào)用connect函數(shù)時,如果發(fā)生中斷,這函數(shù)響應(yīng)中斷,但當中斷返回時,繼續(xù)connect函數(shù)的調(diào)用,直到connect超時失敗或接收到錯誤ICMP包或連接成功
??????? 2.accept()
??????? 如果偵聽進程是非阻塞模式工作,當調(diào)用accept()函數(shù)接收來自客戶端的請求后,返回的socket套接字,默認為阻塞的工作模式。
一、阻塞模型
??? 可能發(fā)生阻塞的套接口調(diào)用分為四種:
??? 1>.輸入操作:read、readv、recv、recvfrom和recvmsg函數(shù)
??? 2>.輸出操作:write、writev、send、sendto和sendmsg函數(shù)
??? 3>.接收外來連接:accept()函數(shù)
??? 4>.初始化外出的連接:connect()函數(shù)
二、I/O模型
??? 1.阻塞I/O
??? 2.非阻塞I/O
??? 3.I/O復(fù)用(select函數(shù))
??? 4.信號驅(qū)動I/O(SIGIO)
??? 5.異步I/O
三、I/O復(fù)用模型的應(yīng)用場合
??? 1.當客戶處理多個描述字時(一般是交互式輸入和網(wǎng)絡(luò)套接口),必須使用I/O復(fù)用。
??? 2.一個客戶同時處理多個套接口
??? 3.如果一個TCP服務(wù)器既要處理偵聽套接口,又要處理已連接套接口,一般也要用到I/O復(fù)用。
??? 4.如果一個服務(wù)器既要處理TCP,又要處理UDP,一般也要使用I/O復(fù)用。
??? 5.如果一個服務(wù)器要處理多個服務(wù)或者多個協(xié)議(inetd守護進程)。
四、拒絕服務(wù)型攻擊
??? 服務(wù)器某一個時刻阻塞于只處理單個客戶,而不能處理其他客戶的需求,這就導(dǎo)致了拒絕服務(wù)型攻擊,可能的解決辦法是:(a)使用非阻塞I/O模型;(b)讓 每個客戶由單獨的控制線程提供服務(wù)(例如,創(chuàng)建子進程或線程來為每個客戶提供服務(wù));(c)對I/O操作設(shè)置超時。
五、connect()函數(shù)
???
1.阻塞模式
??? 客戶端調(diào)用connect()函數(shù)將激發(fā)TCP的三路握手過程,但僅在連接建立成功或出錯時才返回。返回的錯誤可能有以下幾種情況:
??? 1>.如果TCP客戶端沒有接收到SYN分節(jié)的響應(yīng),則返回ETIMEDOUT,阻塞模式的超時時間在75秒(4.4BSD內(nèi)核)到幾分鐘之間。
??? 2>.如果對客戶的SYN的響應(yīng)時RST,則表明該服務(wù)器主機在我們指定的端口上沒有進程在等待與之連接(例如服務(wù)器進程也許沒有啟動),這稱為硬錯,客戶一接收到RST,馬上就返回錯誤ECONNREFUSED.
??? 3>.如果某客戶發(fā)出的SYN在中間的路由器上引發(fā)了一個目的地不可達ICMP錯誤,多次嘗試發(fā)送失敗后返回錯誤號為EHOSTUNREACH或ENETUNREACH.
附加:產(chǎn)生RST的三種情況,一是SYN到達某端口但此端口上沒有正在偵聽的服務(wù)器、二是TCP想取消一個已有連接、三是TCP接收了一個根本不存在的連接上的分節(jié)。
2.非阻塞模式
??? 采用非阻塞的工作模式要考慮一下兩種情況:
1>.如果是連接本機,則調(diào)用connect()函數(shù)會立刻建立。
2>.如果服務(wù)器是網(wǎng)絡(luò)中的用戶,則調(diào)用connect()函數(shù)需要從幾個毫秒的局域網(wǎng)到幾百毫秒或幾秒的廣域網(wǎng)。并且函數(shù)會立刻返回EINPROCESS錯誤,但TCP通信的三路握手過程正在進行,所以可以使用select函數(shù)來檢查這個連接是否建立成功。
??? 源自Berkeley的實現(xiàn)有兩條與select函數(shù)和非阻塞相關(guān)的規(guī)則:
1>.當連接成功建立時,描述字變成可寫。
2>.當連接建立出錯時,描述字變成即可讀又可寫。
六、accept()函數(shù)
1.阻塞模式
??? 如果在一個阻塞套接口上調(diào)用accept()函數(shù),而且沒有新的連接,進程會進入睡眠狀態(tài)。
2.非阻塞模式
??? 如果在一個非阻塞套接口上調(diào)用accept()函數(shù),而且沒有新的連接,將返回EWOULDBLOCK錯誤。
3.一種非阻塞模式例子的問題及解決辦法
??? 問題描述:在服務(wù)器端偵聽套接口采用阻塞的方式工作,并且使用select檢測是否有已經(jīng)建立起的連接,如果有則調(diào)用accept()函數(shù)接收該連接,問 題是如果客戶端首先調(diào)用connect()函數(shù)連接服務(wù)器后立刻又調(diào)用close()函數(shù)關(guān)閉該連接,而在服務(wù)器端,在select()函數(shù)返回和調(diào)用 accept()函數(shù)之間,接收到客戶端的斷開,則會刪除該套接口在已連接套接口中的內(nèi)容,所以服務(wù)器將會阻塞在accept()函數(shù),直到有客戶連接才 返回。
??? 解決辦法:(1).如果用select來獲知何時有連接已就緒可以accept時,總是把偵聽套接口置為非阻塞,同時(2).在后面的accept調(diào)用中 忽略以下錯誤:EWOULDBLOCK(Berkeley的實現(xiàn)在客戶放棄連接時出現(xiàn)的錯誤)、ECONNABORTED(Posix.1g的實現(xiàn)在客戶 放棄連接時出現(xiàn)的錯誤)、EPROTO(SVR4的實現(xiàn)在客戶放棄連接時出現(xiàn)的錯誤)和EINTR(如果信號被捕獲)。
七、select()函數(shù)
??? select()函數(shù)準備好讀的條件:
??? 1>.套接口有數(shù)據(jù)可讀
??? 2>.該連接的讀這一半關(guān)閉(也就是接收了FIN的TCP連接)。對這樣的套接口進行讀操作將不阻塞并返回0(也就是返回EOF)。
??? 3>.該套接口是一個偵聽套接口且已完成的連接數(shù)不為0。
??? 4>.其上有一個套接口錯誤待處理,對這樣的套接口的讀操作將不阻塞并返回-1,并設(shè)置errno,可以通過設(shè)置SO_ERROR選項調(diào)用getsockopt函數(shù)獲得。
??? select()函數(shù)準備好寫的條件:
??? 1>.套接口有可用于寫的空間。
??? 2>.該連接的寫這一半關(guān)閉,對這樣的套接口進行寫操作將產(chǎn)生SIGPIPE信號。
??? 3>.該套接口使用非阻塞的方式connect建立連接,并且連接已經(jīng)異步建立,或則connect已經(jīng)以失敗告終。
??? 4>.其上有一個套接口錯誤待處理。
八、read()函數(shù)和recv函數(shù)
??? read()函數(shù)返回值代表的意義:
??? 1>.如果對方TCP發(fā)送數(shù)據(jù),則套接口就變?yōu)榭勺x且read返回大于0的值(即數(shù)據(jù)的字節(jié)數(shù))。
??? 2>.如果對方TCP發(fā)送一個FIN(對方進程終止),套接口就變?yōu)榭勺x且read返回0(文件結(jié)束)。
??? 3>.如果對方TCP發(fā)送一個RST(對方主機崩潰并重新啟動),套接口就變成可讀且read返回-1,返回的錯誤號errno為ECONNRESET。
九、write()函數(shù)和send函數(shù)
??? 如果向一個接收了FIN的套接字進行寫操作是可行的,但如果向一個接受了RST的套接字進行寫操作則是致命的,內(nèi)核會向該進程發(fā)送一個SIGPIPE信號,返回EPIPO,該錯誤類型默認為終止進程。
SIGPIPE信號
??? 向一個接受了RST的套接字進行寫操作時,內(nèi)核會向該進程發(fā)送一個SIGPIPE信號,該信號的缺省行為是終止進程,因此進程必須捕獲它以免被不情愿的終止。
???
5、 Linux中Socket的數(shù)據(jù)結(jié)構(gòu)
(1) struct sockaddr { //用于存儲套接字地址
unsigned short sa_family;//地址類型
char sa_data[14]; //14字節(jié)的協(xié)議地址
};
(2) struct sockaddr_in{ //in 代表internet
short int sin_family; //internet協(xié)議族
unsigned short int sin_port;//端口號,必須是網(wǎng)絡(luò)字節(jié)順序
struct in_addr sin_addr;//internet地址,必須是網(wǎng)絡(luò)字節(jié)順序
unsigned char sin_zero;//添0(和struct sockaddr一樣大小
};
(3) struct in_addr{
unsigned long s_addr;
};
轉(zhuǎn)載于:https://www.cnblogs.com/xiaOt119/archive/2012/06/27/2566209.html
總結(jié)
以上是生活随笔為你收集整理的阻塞与非阻塞个人小结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript程序开发(十五)—函
- 下一篇: PaperSize.RawKind 属性