Linux系統套接字編程中存在的五個隱患 (1)

發表于:2007-05-26來源:作者:點擊數: 標簽:
Socket API 是 網絡 應用程序 開發 中實際應用的標準 API。盡管該 API 簡單,但是開發新手可能會經歷一些常見的問題。本文識別一些最常見的隱患并向您顯示如何避免它們。 在 4.2 BSD UNIX 操作系統中首次引入,Sockets API 現在是任何操作系統的標準特性。事

Socket API 是網絡應用程序開發中實際應用的標準 API。盡管該 API 簡單,但是開發新手可能會經歷一些常見的問題。本文識別一些最常見的隱患并向您顯示如何避免它們。

  在 4.2 BSD UNIX® 操作系統中首次引入,Sockets API 現在是任何操作系統的標準特性。事實上,很難找到一種不支持 Sockets API 的現代語言。該 API 相當簡單,但新的開發人員仍然會遇到一些常見的隱患。

  本文識別那些隱患并向您顯示如何避開它們。

  隱患 1.忽略返回狀態

  第一個隱患很明顯,但它是開發新手最容易犯的一個錯誤。如果您忽略函數的返回狀態,當它們失敗或部分成功的時候,您也許會迷失。反過來,這可能傳播錯誤,使定位問題的源頭變得困難。

  捕獲并檢查每一個返回狀態,而不是忽略它們??紤]清單 1 顯示的例子,一個套接字 send 函數。


  清單 1. 忽略 API 函數返回狀態
int status, sock, mode;
            
            

/* Create a new stream (TCP) socket */sock =

socket( AF_INET, SOCK_STREAM, 0 );

...status = send( sock, buffer, buflen, MSG_DONTWAIT );

if (status == -1) { /* send failed */ printf( "send failed: %s\n",?

strerror(errno) );

} else { /* send suclearcase/" target="_blank" >cceeded -- or did it? */}


  清單 1 探究一個函數片斷,它完成套接字 send 操作(通過套接字發送數據)。函數的錯誤狀態被捕獲并測試,但這個例子忽略了 send 在無阻塞模式(由 MSG_DONTWAIT 標志啟用)下的一個特性。

  send API 函數有三類可能的返回值:

  • 如果數據成功地排到傳輸隊列,則返回 0。
  • 如果排隊失敗,則返回 -1(通過使用 errno 變量可以了解失敗的原因)。
  • 如果不是所有的字符都能夠在函數調用時排隊,則最終的返回值是發送的字符數。

  由于 send 的 MSG_DONTWAIT 變量的無阻塞性質,函數調用在發送完所有的數據、一些數據或沒有發送任何數據后返回。在這里忽略返回狀態將導致不完全的發送和隨后的數據丟失。

隱患 2.對等套接字閉包

  UNIX 有趣的一面是您幾乎可以把任何東西看成是一個文件。文件本身、目錄、管道、設備和套接字都被當作文件。這是新穎的抽象,意味著一整套的 API 可以用在廣泛的設備類型上。

  考慮 read API 函數,它從文件讀取一定數量的字節。read 函數返回讀取的字節數(最高為您指定的最大值);或者 -1,表示錯誤;或者 0,如果已經到達文件末尾。

  如果在一個套接字上完成一個 read 操作并得到一個為 0 的返回值,這表明遠程套接字端的對等層調用了 close API 方法。該指示與文件讀取相同 —— 沒有多余的數據可以通過描述符讀?。▍⒁?清單 2)。


  清單 2.適當處理 read API 函數的返回值

int sock, status;sock = socket( AF_INET, SOCK_STREAM, 0 );
                
                

...status = read( sock, buffer, buflen );

if (status > 0) { /* Data read from the socket */} else if (status == -1)

{ /* Error, check errno, take action... */} else if (status ==

0) { /* Peer closed the socket, finish the close */ close( sock );

/* Further processing... */}


  同樣,可以用 write API 函數來探測對等套接字的閉包。在這種情況下,接收 SIGPIPE 信號,或如果該信號阻塞,write 函數將返回 -1 并設置 errno 為 EPIPE。

隱患 3.地址使用錯誤(EADDRINUSE)

  您可以使用 bind API 函數來綁定一個地址(一個接口和一個端口)到一個套接字端點??梢栽?STRONG>服務器設置中使用這個函數,以便限制可能有連接到來的接口。也可以在客戶端設置中使用這個函數,以便限制應當供出去的連接所使用的接口。bind 最常見的用法是關聯端口號和服務器,并使用通配符地址(INADDR_ANY),它允許任何接口為到來的連接所使用。

  bind 普遍遭遇的問題是試圖綁定一個已經在使用的端口。該陷阱是也許沒有活動的套接字存在,但仍然禁止綁定端口(bind 返回 EADDRINUSE),它由 TCP 套接字狀態 TIME_WAIT 引起。該狀態在套接字關閉后約保留 2 到 4 分鐘。在 TIME_WAIT 狀態退出之后,套接字被刪除,該地址才能被重新綁定而不出問題。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97