Linux socket 編程中存在的五個隱患

來源:互聯網
上載者:User
前言:        Socket API 是網路應用程式開發中實際應用的標準 API。儘管該 API 簡單,但是


開發新手可能會經曆一些常見的問題。本文識別一些最常見的隱患並向您顯示如何避免它們。 相關文檔:《linux socket 編程》  在 4.2 BSD中首次引入,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 succeeded -- 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 函數來綁定一個地址(一個介面和一個連接埠)到一個通訊端端點。可以在伺服器設定中使用這個函數,以便限制可能有串連到來的介面。也可以在用戶端設定中使用這個函數,以便限制應當供出去的串連所使用的介面。bind 最常見的用法是關聯末端口號和伺服器,並使用萬用字元地址(INADDR_ANY),它允許任何介面為到來的串連所使用。  bind 普遍遭遇的問題是試圖綁定一個已經在使用的連接埠。該陷阱是也許沒有活動的通訊端存在,但仍然禁止綁定連接埠(bind 返回 EADDRINUSE),它由 TCP 通訊端狀態 TIME_WAIT 引起。該狀態在通訊端關閉後約保留 2 到 4 分鐘。在 TIME_WAIT 狀態退出之後,通訊端被刪除,該地址才能被重新綁定而不出問題。等待 TIME_WAIT 結束可能是令人惱火的一件事,特別是如果您正在開發一個通訊端伺服器,就需要停止伺服器來做一些改動,然後重啟。幸運的是,有方法可以避開 TIME_WAIT 狀態。可以給通訊端應用 SO_REUSEADDR 通訊端選項,以便連接埠可以馬上重用。考慮清單 3 的例子。在綁定地址之前,我以 SO_REUSEADDR 選項調用 setsockopt。為了允許地址重用,我設定整型參數(on)為 1 (不然,可以設為 0 來禁止地址重用)。 清單 3.使用 SO_REUSEADDR 通訊端選項避免地址使用錯誤
int sock, ret, on;struct sockaddr_in servaddr;/* Create a new stream (TCP) socket */sock = socket( AF_INET, SOCK_STREAM, 0 ):/* Enable address reuse */on = 1;ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR,
 &on, sizeof(on) );/* Allow connections to port 8080 from any available interface */memset( &servaddr, 0, sizeof(servaddr) );servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl( INADDR_ANY );servaddr.sin_port = htons( 45000 );/* Bind to the address (interface/port) */ret = bind( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) );     
在應用了 SO_REUSEADDR 選項之後,bind API 函數將允許地址的立即重用。  隱患 4.發送結構化資料通訊端是發送無結構二進位位元組流或 ASCII 資料流(比如 HTTP 上的 HTTP 頁面,或 SMTP 上的電子郵件)的完美工具。但是如果試圖在一個通訊端上發送位元據,事情將會變得更加複雜。  比如說,您想要發送一個整數:您可以肯定,接收者將使用同樣的方式來解釋該整數嗎?運行在同一架構上的應用程式可以依賴它們共同的平台來對該類型的資料做出相同的解釋。但是,如果一個運行在高位優先的 IBM PowerPC 上的用戶端發送一個 32 位的整數到一個低位優先的 Intel x86,那將會發生什麼呢?位元組排列將引起不正確的解釋。  通過通訊端發送一個 C 結構會怎麼樣呢?這裡,也會遇到麻煩,因為不是所有的編譯器都以相同的方式排列一個結構的元素。結構也可能被壓縮以便使浪費的空間最少,這進一步使結構中的元素錯位。  幸好,有解決這個問題的方案,能夠保證兩端資料的一致解釋。過去,遠端程序呼叫(Remote Procedure Call,RPC)套裝工具提供所謂的外部資料表示(External Data Representation,XDR)。XDR 為資料定義一個標準的表示來支援異構網路應用程式通訊的開發。現在,有兩個新的協議提供相似的功能。可延伸標記語言 (XML)/遠端程序呼叫(XML/RPC)以 XML 格式安排 HTTP 上的程序呼叫。資料和中繼資料用 XML 進行編碼並作為字串傳輸,並通過主機架構把值和它們的物理表示分開。SOAP 跟隨 XML-RPC,以更好的特性和功能擴充了它的思想。參見 參考資料小節,擷取更多關於每個協議的資訊。  隱患 5.TCP 中的幀同步假定TCP 不提供幀同步,這使得它對於面向位元組流的協議是完美的。這是 TCP 與 UDP(User Datagram Protocol,使用者資料包通訊協定)的一個重要區別。UDP 是面向訊息的協議,它保留髮送者和接收者之間的訊息邊界。TCP 是一個面向流的協議,它假定正在通訊的資料是無結構的, 1 所示。圖 1.UDP 的幀同步能力和缺乏幀同步的 TCP  圖 1 的上部說明一個 UDP 用戶端和伺服器。左邊的對等層完成兩個通訊端的寫操作,每個 100 位元組。協議棧的 UDP 層追蹤寫的數量,並確保當右邊的接收者通過通訊端擷取資料時,它以同樣數量的位元組到達。換句話說,為讀者保留了寫者提供的訊息邊界。現在,看圖 1 的底部.它為 TCP 層示範了相同粒度的寫操作。兩個獨立的寫操作(每個 100 位元組)寫入流通訊端。但在本例中,流通訊端的讀者得到的是 200 位元組。協議棧的 TCP 層彙總了兩次寫操作。這種彙總可以發生在 TCP/IP 協議棧的寄件者或接收者中任何一方。重要的是,要注意到彙總也許不會發生 —— TCP 只保證資料的有序發送。  對大多數開發人員來說,該陷阱會引起困惑。您想要獲得 TCP 的可靠性和 UDP 的幀同步。除非改用其他的傳輸協議,比如流傳輸控制通訊協定(STCP),否則就要求應用程式層開發人員來實現緩衝和分段功能。   調試通訊端應用程式的工具  GNU/Linux 提供幾個工具,它們可以協助您發現通訊端應用程式中的一些問題。此外,使用這些工具還有教育意義,而且能夠協助解釋應用程式和 TCP/IP 協議棧的行為。在這裡,您將看到對幾個工具的概述。查閱下面的 參考資料 瞭解更多的資訊。  查看網路子系統的細節  netstat 工具提供查看 GNU/Linux 網路子系統的能力。使用 netstat,可以查看當前活動的串連(按單個協議進行查看),查看特定狀態的串連(比如處於監聽狀態的伺服器通訊端)和許多其他的資訊。清單 4 顯示了 netstat 提供的一些選項和它們啟用的特性。
清單 4.netstat 公用程式的用法模式
View all TCP sockets currently active$ netstat --tcpView all UDP sockets$ netstat --udpView all TCP sockets in the listening state$ netstat --listeningView the multicast group membership information$ netstat --groupsDisplay the list of masqueraded connections$ netstat --masqueradeView statistics for each protocol$ netstat --statistics
   儘管存在許多其他的公用程式,但 netstat 的功能很全面,它覆蓋了 route、ifconfig 和其他標準 GNU/Linux 工具的功能。  監視流量  可以使用 GNU/Linux 的幾個工具來檢查網路上的低層流量。tcpdump 工具是一個比較老的工具,它從網上“嗅探”網路資料包,列印到 stdout 或記錄在一個檔案中。該功能允許查看應用程式產生的流量和 TCP 產生的低層流量控制機制。一個叫做 tcpflow 的新工具與 tcpdump 相輔相成,它提供協議串流分析和適當地重構資料流的方法,而不管資料包的順序或重發。清單 5 顯示 tcpdump 的兩個用法模式。
  清單 5.tcpdump 工具的用法模式
Display all traffic on the eth0 interface for the local host$ tcpdump -l -i eth0Show all traffic on the network coming from or going to host plato$ tcpdump host platoShow all HTTP traffic for host camus$ tcpdump host camus and (port http)View traffic coming from or going to TCP port 45000 on the local host$ tcpdump tcp port 45000
tcpdump 和 tcpflow 工具有大量的選項,包括建立複雜過濾運算式的能力。查閱下面的參考資料 擷取更多關於這些工具的資訊。 tcpdump 和 tcpflow 都是基於文本的命令列工具。如果您更喜歡圖形化使用者介面(GUI),有一個開放源碼工具 Ethereal 也許適合您的需要。Ethereal 是一個專業的協議分析軟體,它可以協助調試應用程式層協議。它的插入式架構(plug-in architecture)可以分解協議,比如 HTTP 和您能想到的任何協議(寫本文的時候共有 637 個協議)。
 

上一篇:《Linux系統下USB網路攝影機驅動開發》
下一篇:《LINUX的系統核心空間的保護》

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.