青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

   C++ 技術中心

   :: 首頁 :: 聯系 ::  :: 管理
  160 Posts :: 0 Stories :: 87 Comments :: 0 Trackbacks

公告

鄭重聲明:本BLOG所發表的原創文章,作者保留一切權利。必須經過作者本人同意后方可轉載,并注名作者(天空)和出處(CppBlog.com)。作者Email:coder@luckcoder.com

留言簿(27)

搜索

  •  

最新隨筆

最新評論

評論排行榜

在 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 succeeded -- or did it? */
}

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

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

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

由于 sendMSG_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 并設置 errnoEPIPE


隱患 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,那將會發生什么呢?字節排列將引起不正確的解釋。

字節交換還是不呢?

Endianness 是指內存中字節的排列順序。高位優先(big endian) 按最高有效字節在前排列,然而 低位優先(little endian) 按照最低有效字節在前排序。

高位優先架構(比如 PowerPC®)比低位優先架構(比如 Intel® Pentium® 系列,其網絡字節順序是高位優先)有優勢。這意味著,對高位優先的機器來說,在 TCP/IP 內控制數據是自然有序的。低位優先架構要求字節交換 —— 對網絡應用程序來說,這是一個輕微的性能弱點。

通過套接字發送一個 C 結構會怎么樣呢?這里,也會遇到麻煩,因為不是所有的編譯器都以相同的方式排列一個結構的元素。結構也可能被壓縮以便使浪費的空間最少,這進一步使結構中的元素錯位。

幸好,有解決這個問題的方案,能夠保證兩端數據的一致解釋。過去,遠程過程調用(Remote Procedure Call,RPC)套裝工具提供所謂的外部數據表示(External Data Representation,XDR)。XDR 為數據定義一個標準的表示來支持異構網絡應用程序通信的開發。

現在,有兩個新的協議提供相似的功能。可擴展標記語言/遠程過程調用(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 --tcp
View all UDP sockets
$ netstat --udp
View all TCP sockets in the listening state
$ netstat --listening
View the multicast group membership information
$ netstat --groups
Display the list of masqueraded connections
$ netstat --masquerade
View statistics for each protocol
$ netstat --statistics

盡管存在許多其他的實用程序,但 netstat 的功能很全面,它覆蓋了 routeifconfig 和其他標準 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 eth0
Show all traffic on the network coming from or going to host plato
$ tcpdump host plato
Show 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

tcpdumptcpflow 工具有大量的選項,包括創建復雜過濾表達式的能力。查閱下面的 參考資料 獲取更多關于這些工具的信息。

tcpdumptcpflow 都是基于文本的命令行工具。如果您更喜歡圖形用戶界面(GUI),有一個開放源碼工具 Ethereal 也許適合您的需要。Ethereal 是一個專業的協議分析軟件,它可以幫助調試應用層協議。它的插入式架構(plug-in architecture)可以分解協議,比如 HTTP 和您能想到的任何協議(寫本文的時候共有 637 個協議)。


總結

套接字編程是容易而有趣的,但是您要避免引入錯誤或至少使它們容易被發現,這就需要考慮本文中描述的這 5 個常見的陷阱,并且采用標準的防錯性程序設計實踐。GNU/Linux 工具和實用程序還可以幫助發現一些程序中的小問題。記住:在查看實用程序的幫助手冊時候,跟蹤相關的或“請參見”工具。您也許會發現一個必要的新工具。


參考資料

學習

獲得產品和技術

  • tcpdumptcpflow 實用程序可以用來監控網絡流量。

  • Ethereal network protocol analyzer 提供 tcpdump 的功能,它具有圖形用戶界面和可伸縮的插入式架構。

  • 免費索取 SEK for Linux(兩張 DVD),它包含來自 DB2®、Lotus®、Rational®、Tivoli® 以及 WebSphere® 的最新 IBM 試用軟件的 Linux 版本。

  • IBM 試用軟件 在 Linux 上構建您的下一個開發項目,可以直接在 developerWorks 上下載。


討論

posted on 2013-07-01 10:44 C++技術中心 閱讀(1701) 評論(1)  編輯 收藏 引用 所屬分類: Linux 編程

Feedback

# re: Linux 套接字編程中的 5 個隱患 2013-07-03 09:19 易寶@byhh
這算什么?copy IBM的。 然后放首頁?   回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲午夜在线观看视频在线| 亚洲精品无人区| 亚洲一区精品在线| 国产精品美女www爽爽爽| 亚洲一区二区三区777| 日韩视频免费在线| 欧美视频第二页| 性久久久久久| 久久国产主播精品| 亚洲国产专区校园欧美| 亚洲三级电影在线观看| 欧美连裤袜在线视频| 亚洲新中文字幕| 午夜精品久久久久久久蜜桃app | 亚洲丶国产丶欧美一区二区三区| 久久精品五月| 亚洲精品小视频| 一区二区三区久久精品| 国产日韩欧美三区| 欧美黄色片免费观看| 欧美三区不卡| 看欧美日韩国产| 欧美日韩在线观看一区二区三区 | 在线播放日韩欧美| 亚洲欧洲精品一区二区| 国产精品卡一卡二卡三| 美女999久久久精品视频| 欧美激情精品久久久久久久变态| 亚洲女性喷水在线观看一区| 久久国产一区| 亚洲女人天堂av| 免费观看成人鲁鲁鲁鲁鲁视频| 亚洲欧美日韩一区在线观看| 欧美一区二区在线免费播放| 欧美一区2区三区4区公司二百| 亚洲第一综合天堂另类专| 亚洲精品一区在线观看| 国产一区二区久久精品| 亚洲激情中文1区| 国产九九精品| 亚洲美女电影在线| 激情久久五月天| 亚洲桃色在线一区| 亚洲人成人一区二区在线观看| 亚洲欧美日韩精品久久奇米色影视| 亚洲高清av在线| 亚洲伊人一本大道中文字幕| 一区二区日韩| 久久综合色播五月| 午夜精品国产更新| 欧美伦理视频网站| 欧美成人蜜桃| 激情综合久久| 亚洲欧美高清| 亚洲一二三区在线观看| 欧美成人午夜激情| 欧美激情精品久久久| 国产一区二区三区最好精华液| 一区二区免费在线视频| 在线一区亚洲| 欧美精品一卡| 亚洲高清视频一区| 亚洲黄色毛片| 久久综合国产精品| 奶水喷射视频一区| 亚洲黄色视屏| 欧美激情小视频| 欧美一区二视频| 欧美日韩亚洲一区二区三区在线 | 老司机免费视频一区二区| 国产精品入口夜色视频大尺度| 亚洲精品一区二| 夜夜嗨av一区二区三区免费区| 欧美成人精品在线| 最新国产成人在线观看| 99精品国产福利在线观看免费| 免费久久99精品国产自| 亚洲国产精品成人一区二区| 亚洲国产精品va在线看黑人动漫 | 欧美国产免费| 亚洲精品一区二区三区四区高清| 亚洲黑丝在线| 欧美一区二区三区啪啪| 性做久久久久久免费观看欧美| 欧美性猛交xxxx乱大交蜜桃| 亚洲亚洲精品在线观看| 欧美一区三区三区高中清蜜桃| 国产女人aaa级久久久级| 欧美一区国产一区| 欧美高清日韩| 亚洲小说区图片区| 国产亚洲视频在线| 毛片基地黄久久久久久天堂| 亚洲欧洲日产国码二区| 亚洲欧美日韩综合| 国产在线不卡| 欧美日本一区二区高清播放视频| av成人黄色| 久久一二三四| 一区二区三区偷拍| 国产一区二区精品丝袜| 亚洲免费播放| 亚洲第一天堂无码专区| 亚洲精品小视频| 欧美日韩一卡| 久久狠狠亚洲综合| 亚洲人成在线播放网站岛国| 欧美一区二区三区视频在线观看| 欲香欲色天天天综合和网| 欧美精品成人91久久久久久久| 亚洲一二三区精品| 欧美激情国产精品| 欧美亚洲免费| 一区二区不卡在线视频 午夜欧美不卡在| 欧美午夜在线| 欧美www视频| 亚洲视频在线一区| 亚洲福利久久| 久久久久久69| 亚洲永久免费观看| 亚洲激情精品| 狠狠综合久久| 国产欧美日韩综合一区在线播放| 久久全国免费视频| 亚洲电影第三页| 久久久亚洲欧洲日产国码αv | 欧美高清视频在线| 欧美一区视频在线| 99视频一区二区| 亚洲国内精品在线| 免费中文日韩| 久久久久国产精品一区三寸| 亚洲欧美日韩国产成人| 亚洲精品欧洲| 亚洲欧洲在线免费| 亚洲第一黄色| 亚洲第一福利社区| 国产在线播精品第三| 国产亚洲激情视频在线| 国产精品久久久久久久久久妞妞| 欧美久久一级| 欧美日韩国产精品成人| 欧美寡妇偷汉性猛交| 欧美xxx成人| 欧美国产日韩一区二区三区| 国产精品高潮在线| 久久久99免费视频| 欧美一区二区三区在线播放| 午夜欧美不卡精品aaaaa| 亚洲视频免费| 午夜精品久久久| 欧美一区二区视频在线观看| 欧美亚洲在线视频| 欧美一区二区三区精品| 欧美一区二区三区免费视频| 欧美在线一二三| 久久综合狠狠综合久久综合88 | 欧美激情在线有限公司| 欧美成人免费播放| 最近看过的日韩成人| 亚洲精品久久久久久久久久久久| 亚洲欧洲一区| 在线亚洲免费视频| 国产精品99久久久久久久女警 | 欧美99在线视频观看| 国产精品福利在线观看网址| 免费h精品视频在线播放| 欧美波霸影院| 欧美三区免费完整视频在线观看| 国产精品成人免费视频| 国产一区久久| 亚洲欧洲中文日韩久久av乱码| 99精品国产在热久久婷婷| 亚洲综合不卡| 久久久人成影片一区二区三区观看| 欧美成人嫩草网站| 亚洲精品日韩在线观看| 亚洲一区二区三区午夜| 久久夜色精品国产欧美乱| 欧美日韩福利| 精品动漫3d一区二区三区免费版 | 又紧又大又爽精品一区二区| 亚洲免费观看视频| 欧美一区二区三区精品电影| 欧美国产精品久久| 亚洲视频在线观看三级| 久久五月婷婷丁香社区| 国产精品sss| 亚洲激情视频在线播放| 亚洲欧美在线高清| 亚洲日韩欧美一区二区在线| 亚洲香蕉伊综合在人在线视看| 久久成年人视频| 亚洲欧洲精品一区| 久久精品一区| 国产麻豆午夜三级精品| 亚洲乱码国产乱码精品精| 久久久亚洲国产天美传媒修理工| 99re视频这里只有精品| 欧美/亚洲一区|