給套接口上的I/O設置超時
1.調用alarm,在調用超過指定時間時產生SIGALARM信號,這涉及到信號處理,並且可能和進程中其餘的alarm衝突
2.使用select阻塞在等待I/O上,select內部有時間限制,一次代替在read和write上阻塞超時
3.使用新的SO_RCVTIMEO和SO_SNDTIMEO套接字選項,這種方法存在一個問題,即不是全部的系統都支持這兩個選項。
這三種技術均可以用做輸入和輸出操做,但咱們還想要一種支持connect超時的技術,由於TCP中的默認超時時間很長(75s),只有套接口爲非阻塞方式時,才能夠調用select爲connect設置超時,connect並不支持SO_RCVTIMEO和SO_SNDTIMEO。前兩種技術能夠應用於任何描述符,第三種技術只能應用於套接字。
alarm的原理
alarm基於信號將中斷阻塞的socekt操做,若是alarm產生信號之時connect仍未返回,EINTR錯誤即表示connect超時。
這種技術只能提早完成超時,而不能延長超時,好比connect的默認超時時長是75s,alarm能夠提早爲50s超時,卻不能設置成80s超時。
用信號處理一個應答時沒有問題,處理多個應答的時候就必須解決可能的衝突。
recv和send
recv和send的前三個參數和read、write相同,第四個參數由如下的一個或者多個flag或組成
MSG_DONTWAIT
將單個I/O操做設置爲非阻塞,而不須要在套接口上設置非阻塞標記,執行I/O操做,而後關閉非阻塞。
MSG_WAITALL
告訴內核,沒有讀到請求的字節數以前不要返回,即便設定了這個標記,若是發生下列問題,返回的字節數仍然會比請求的要少
1.捕獲一個信號
2.鏈接被終止
3.套接口上發生錯誤。
readv和writev
相似於read和write,但讓咱們能夠在一個函數調用中操做多個緩衝區,這些操做被成爲分散讀和集中寫。
readv和writev可用於任何描述字,並且writev是一個原子操做。
recvmsg和sendmsg
這兩個函數是最通用的I/O函數,能夠用recvmsg替代read、readv、recv、recvfrom,sendmsg也能夠替代其餘的write函數。
在不讀出數據的時候,怎麼知道套接口中有多少數據可讀?
1.若是沒有其餘數據可讀還有其餘事情要作,可使用非阻塞I/O。
2.若是想檢查一下數據,而使數據扔保存在接收隊列中,可使用MSG_PEEK,若是想這麼作,又不肯定必定有數據可讀,能夠把MSG_PEEK和非阻塞套接口一塊兒使用,或者和MSGDONTWAIT一塊兒使用。
3.一些支持ioctl的FIONREAD命令,
標準I/O庫用於套接口
對於任何文件描述符,調用fdopen能夠返回一個標準I/O流,對於一個標準I/O流,調用fileno能夠得到文件描述符。多路複用只能用於描述字,因此須要把標準I/O轉爲文件描述符。
TCP和UDP是全雙工的,標準I/O流也能夠是全雙工的,只要以r+方式打開便可,可是對這樣的流不能在一個輸出函數後緊接着一個輸入函數,必須插入一個fflush、fseek、fsetpos、或rewind調用,一樣,不能在一個輸入函數後緊接一個輸出函數,必須插入一個fseek、fsetpos或rewind。除非輸入函數遇到一個文件描述符,後三個函數的問題是他們都會調用lseek,可lseek會在套接口上失敗。
解決這個問題的最簡單方法是:爲一個套接字打開兩個標準I/O流,一個讀、一個寫。
問題是標準I/O庫自動進行緩衝,標準I/O庫執行三種緩衝
1.徹底緩衝,意味着只有在如下狀況才進行I/O:緩衝區滿;進程調用fflush或者進程調用exit退出。標準I/O緩衝區大小一般爲8192.
2.行緩衝:遇到一個換行符;進程調用fflush或者進程調用exit退出。
3.不緩衝,意味着每次調用標準I/O函數都進行I/O。
大部分UNIX的標準I/O遵循瞭如下原則
1.標準錯誤輸出老是不緩衝
2。標準輸入和標準輸出是全緩衝的,除非它們是一個終端設備,那樣它們是行緩衝的。
3.其餘的流逗是全緩衝的,除非他們是一個終端設備,那樣它們是行緩衝的。
套接口不是終端設備;有一些標準I/O庫對大於255的文件描述符處理有問題。
事務TCP
在TCP基礎上作了少許修改,以免在最近通訊過的主機之間進行三次握手(客戶和服務器首次通訊仍是須要握手的,之後只要高速緩存的信息尚未過期就不須要握手)。
T/TCP把SYN、FIN和數據合併到單個分節中,前提是數據的長度小於MSS。T/TCP保持了TCP的可靠性。