版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、unix網(wǎng)絡(luò)編程筆記unix網(wǎng)絡(luò)編程筆記2010-06-04 16:09索引:1處理SIGCHLD信號2捕獲信號時,注意處理被中斷的系統(tǒng)調(diào)用3accept返回前連接夭折的處理4具有多個輸入的處理5SIGPIPE的產(chǎn)生和處理6處理服務(wù)器主機崩潰7處理服務(wù)器主機崩潰重啟8處理服務(wù)器主機關(guān)機9網(wǎng)絡(luò)函數(shù)的可重入問題10套接口設(shè)置超時的方法11輔助數(shù)據(jù)12如何得知套接口接收隊列中有多少數(shù)據(jù)?13UNIX域協(xié)議14UNIX域套接口使用套接口函數(shù)的一些差別和限制15描述字傳遞機制16非阻塞套接口I/O 17服務(wù)器程序常見設(shè)計方法18注意網(wǎng)絡(luò)編程的移植性問題19注意對等方的不合理行為20開發(fā)和使用應(yīng)用程序框架
2、21在應(yīng)用程序中中實現(xiàn)keep-alive機制22理解TCP的寫操作23使應(yīng)用程序事件驅(qū)動24不要試圖繞過TIME-WAIT狀態(tài)25服務(wù)器應(yīng)當(dāng)設(shè)置SO_REUSEADDR選項26盡量使用大型寫操作代替多個小規(guī)模寫操作27注意異步connect的可移植問題28避免數(shù)據(jù)拷貝在使用之前置sockaddr_in結(jié)構(gòu)為0 29理解緩沖區(qū)大小對TCP性能的影響30理解已連接UDP套接字-1.處理SIGCHLD信號當(dāng)編寫fork子進程處理連接的服務(wù)器程序時,子進程退出會給父進程產(chǎn)生SIGCHLD信號,父進程若不處理該信號會導(dǎo)致僵尸進程。處理SIGCHLD信號,使用waitpid調(diào)用,不能使用wait簡單處理
3、。一般的處理方法如下(信號處理函數(shù)):void sig_chld(int signo)pid_t pid;int stat;while(pid=waitpid(-1,&stat,WNOHANG)0)continue;return;2.捕獲信號時,注意處理被中斷的系統(tǒng)調(diào)用信號處理可能會中斷慢系統(tǒng)調(diào)用,所以我們必須對慢系統(tǒng)調(diào)用返回EINTR錯誤做準備。一般處理方法如下(以accept為例):for(;)clilen=sizeof(cliaddr);if(connfd=accept(listenfd,(SA*)&cliaddr,&clilen)0)if(errno=EINTR)continue;el
4、se err_sys(accept error);此法對accept、read、write、select、open等合適;但connect調(diào)用不能重啟,若connect返回EINTR,我們不能再調(diào)用它,否則立即返回錯誤。3.accept返回前連接夭折的處理連接在listen后建立,在accept前夭折,此時accept可能會返回錯誤,對此必須處理。但對于夭折的連接處理依賴于實現(xiàn),源自Berkekey的實現(xiàn)在內(nèi)核中處理夭折的連接,服務(wù)器進程根本看不到,若當(dāng)前沒有新連接,則accept阻塞;大多數(shù)SVR4實現(xiàn)會返回一個錯誤給進程,作為accept的返回,此值可能是EPROTO(協(xié)議錯)errno值
5、;Posix.1g要求返回ECONNABORTED(軟件引起的連接夭折)。所以,在ECONNABORTED錯誤情況下,服務(wù)器可以忽略錯誤而簡單的再調(diào)用accept一次。經(jīng)過測試,在Solaris8和AIX4.3下返回ECONNABORTED,但在SCO Openserver 5.05下返回EINVAL。4.具有多個輸入的處理當(dāng)工作在有兩個或多個描述字的情況下,不能只阻塞于某個特定源輸入中,而是應(yīng)該阻塞于任一個源的輸入中。否則在網(wǎng)絡(luò)描述字中會出現(xiàn)有異常數(shù)據(jù)而沒有讀到,導(dǎo)致出錯的情況。方法是使用select或poll。5.SIGPIPE的產(chǎn)生和處理在一個服務(wù)器進程終止的情況下,終止關(guān)閉了描述字,此
6、時客戶對此描述字寫,服務(wù)器TCP接收到來自客戶的數(shù)據(jù),由于先前打開那個套接口的進程已經(jīng)終止,所以以RST響應(yīng)??蛻舳丝赡軙盏较惹瓣P(guān)閉時的FIN,也可能收到后面的RST,這依賴于當(dāng)時的具體情況。因為同時有FIN和RST時,RST優(yōu)先于FIN。當(dāng)進程向接收了RST的套接口進行寫操作時,內(nèi)核個該進程發(fā)一個SIGPIPE信號,此信號的缺省行為是終止進程,所以,進程必須捕獲該信號以免不情愿的被終止。進程不論是捕獲了該信號并從其信號處理程序返回,還是不理會該信號,寫操作都會返回EPIPE錯誤。寫一個已接收FIN的套接口是可行的,但寫一個已接收了RST的套接口則是錯誤的。處理SIGPIPE的建議方法取決于
7、它發(fā)生時應(yīng)用想做什么。如果沒有什么特殊的情況處理,可將信號處理方法簡單的設(shè)置為SIG_IGN,并假設(shè)后續(xù)的寫操作將捕捉EPIPE錯誤并終止。若在信號處理程序中處理,要注意的是,如果使用了多個套接口,該信號的遞交無法知道是哪個套接口出的錯。6.處理服務(wù)器主機崩潰假設(shè)服務(wù)器主機已經(jīng)崩潰,客戶此時寫數(shù)據(jù),客戶TCP會持續(xù)重傳數(shù)據(jù)分節(jié),若客戶的數(shù)據(jù)分節(jié)根本沒有響應(yīng),則錯誤為ETIMEDOUT;若某些中間路由器判定服務(wù)器主機不可達,且以一個目的地不可達餓ICMP消息響應(yīng),則錯誤是EHOSTUNREACH或ENETUNREACH。以上情況只有向服務(wù)器主機發(fā)送數(shù)據(jù)時,才能檢測出它已經(jīng)崩潰。如果不主動發(fā)送也想
8、檢測出崩潰情況,則需要設(shè)置套接口選項SO_KEEPALIVE。7.處理服務(wù)器主機崩潰重啟當(dāng)服務(wù)器主機崩潰并重啟后,客戶向服務(wù)器發(fā)送數(shù)據(jù),由于服務(wù)器重啟,它的TCP丟失了崩潰前的所有連接信息,所以服務(wù)器TCP對接收到的客戶數(shù)據(jù)分節(jié)以RST響應(yīng)。若客戶阻塞于讀,則返回ECONNRESET錯誤。8.處理服務(wù)器主機關(guān)機服務(wù)器關(guān)機會終止所有進程,進程退出時會關(guān)閉描述字,所以該情況的處理類似于SIGPIPE中服務(wù)器進程終止的討論。9.網(wǎng)絡(luò)函數(shù)的可重入問題歷史上,gethostbyname、gethostbyname2、gethostbyaddr、getservbyname和getservbyport是不可
9、重入的。一些支持線程的實現(xiàn)提供了相應(yīng)的可重入版本(以_r結(jié)尾),也有些實現(xiàn)提供了這些函數(shù)的使用線程特定數(shù)據(jù)的可重入版本。inet_pton和inet_ntop總是可重入的。歷史上inet_ntoa是不可重入的,但一些實現(xiàn)提供了使用線程特定數(shù)據(jù)的可重入版本。getaddrinfo只有在它自己調(diào)用的是可重入函數(shù)時才是可重入的。getnameinfo只有在它自己調(diào)用的是可重入函數(shù)時才是可重入的。10.套接口設(shè)置超時的方法有三種方法:調(diào)用alarm,在到達指定時間時產(chǎn)生SIGALRM信號,必要時結(jié)合sigsetjmp和siglongjmp進行使用。使用select的時間機制來設(shè)置超時。使用新的SO_R
10、CVTIMEO和SO_SNDTIMEO套接口選項。該法的缺點是不是所有的實現(xiàn)都支持它們,一旦為每個描述字設(shè)置了這個選項,并指定了超時值,那么這個超時值對該套接口上的所有讀/寫操作都起作用,所以只需設(shè)置一次選項。但它們只能用于讀/寫操作,沒法為connect設(shè)置超時。當(dāng)超時發(fā)生,函數(shù)返回EWOULDBLOCK。11.輔助數(shù)據(jù)在sendmsg和recvmsg中可以使用msghdr結(jié)構(gòu)中的msg_control和msg_controllen成員發(fā)送和接收輔助數(shù)據(jù)(ancillary data)。輔助數(shù)據(jù)的另一個叫法是控制信息(control information)。輔助數(shù)據(jù)的各種用法如下:協(xié)議cm
11、sg_level cmsg_type說明IPv4 IPPROTO_IP IP_RECVDSTADDR接收UDP數(shù)據(jù)報的目的地址IP_RECVIF接收UDP數(shù)據(jù)報的接口索引IPv6 IPPROTO_IPV6 IPV6_DSTOPTS指定/接收目標(biāo)選項IPV6_HOPLIMIT指定/接收跳限IPV6_HOPOPTS指定/接收步跳選項IPV6_NEXTHOP指定下一跳地址IPV6_PKTINFO指定/接收分組信息IPV6_RTHDR指定/接收路由頭部Unix域SOL_SOCKET SCM_RIGHTS發(fā)送/接收描述字SCM_CREDS發(fā)送/接收用戶憑證輔助數(shù)據(jù)由一個或多個輔助數(shù)據(jù)對象組成,每個對象由
12、一個cmsghdr結(jié)構(gòu)開頭,該結(jié)構(gòu)在sys/socket.h中定義如下:struct cmsghdrsocklen_t cmsg_len;/*length in bytes,including this structure*/int cmsg_level;/*originating protocol*/int cmsg_type;/*protocol-specific type followed by unsigned char cmsg_data*/;實際數(shù)據(jù)在cmsghdr結(jié)構(gòu)后面,msg_control指向的輔助數(shù)據(jù)必須按cmsghdr結(jié)構(gòu)進行對齊,所以在cmsg_type成員和實際數(shù)據(jù)
13、之間可能有填充字節(jié),在數(shù)據(jù)之后,下一個對象之前也可能有填充字節(jié)。使用如下的宏屏蔽可能出現(xiàn)的填充字節(jié):#include sys/socket.h#include sys/param.h struct cmsghdr*CMSG_FIRSTHDR(struct msghdr*mhdrptr);返回:指向第一個cmsghdr結(jié)構(gòu)的指針,無輔助數(shù)據(jù)時為NULL struct cmsghdr*CMSG_NXTHDR(struct msghdr*mhdrptr,struct cmsghdr*cmsgptr);返回:指向下一個cmsghdr結(jié)構(gòu)的指針,不再有輔助數(shù)據(jù)對象時為NULL unsigned char
14、*CMSG_DATA(struct cmsghdr*cmsgptr);返回:指向與cmsghdr結(jié)構(gòu)關(guān)聯(lián)的數(shù)據(jù)的第一個字節(jié)的指針unsigned int CMSG_LEN(unsigned int length);返回:給定數(shù)據(jù)量下存儲在cmsg_len中的值unsigned int CMSG_SPACE(unsigned int length);返回:給定數(shù)據(jù)量寫一個輔助數(shù)據(jù)對象的總大小CMSG_LEN和CMSG_SPACE的區(qū)別在于,前者不將填充字節(jié)計算在內(nèi),因此等于cmsg_len的值,但后者將這些填充字節(jié)都計算在內(nèi),因此在動態(tài)申請輔助數(shù)據(jù)對象的數(shù)據(jù)空間時使用這個值。12.如何得知套接口
15、接收隊列中有多少數(shù)據(jù)?有三種方法:如果在沒有數(shù)據(jù)可讀時還有其他事情要做,為了不阻塞在內(nèi)核中,可以使用非阻塞I/O。如果想檢查數(shù)據(jù)而使數(shù)據(jù)仍留在接收隊列中,可以使用MSG_PEEK標(biāo)志。如果想避免阻塞,可以把此標(biāo)志和非阻塞套接口相結(jié)合,或與MSG_DONTWAIT標(biāo)志結(jié)合使用。注意的是,一個字節(jié)流套接口接收隊列的數(shù)據(jù)量在兩次連續(xù)的recv調(diào)用之間可能會改變,而UDP套接口不會。一些實現(xiàn)支持ioctl的FIONREAD命令。Ioctl的第三個參數(shù)是一個指向整數(shù)的指針,在該整數(shù)中返回的值是套接口接收隊列中數(shù)據(jù)的字節(jié)數(shù)。這個值是隊列中字節(jié)數(shù)的總和,對UDP套接口來包括在隊列中的所有數(shù)據(jù)報。13.UNI
16、X域協(xié)議UNIX域協(xié)議并不是一個實際的協(xié)議族,它只是在同一臺主機上進行C/S通信時,使用與在不同主機上的C/S通信時相同的API的一種方法。UNIX域提供了兩種類型的套接口:字節(jié)流套接口(與TCP類似)和數(shù)據(jù)報套接口(與UDP類似)。使用UNIX域協(xié)議有三個原因:在源自Berkeley的實現(xiàn)中,當(dāng)通信雙方位于同一臺主機上時,UNIX域套接口的速度通常是TCP套接口的兩倍。UNIX域套接口可以用來在同一臺主機上的各進程之間傳遞描述字。UNIX域套接口的較新實現(xiàn)中可以向服務(wù)器提供客戶的憑證(用戶ID和組ID),這能提供附加的安全檢查。UNIX域套接口地址結(jié)構(gòu)如下:#include struct s
17、ockaddr_unuint8_t sun_len;sa_family_t sun_family;/*AF_LOCAL*/char sun_path104;/*null_terminated pathname*/;sun_path數(shù)組中存放的路徑名必須以空字符結(jié)尾。系統(tǒng)提供了SUN_LEN宏,他以一個指向sockaddr_un結(jié)構(gòu)的指針為參數(shù),返回該結(jié)構(gòu)的長度,長度里包括路徑名中的非空字節(jié)數(shù)。未指定地址以空字符串的路徑名表示,這是UNIX域中與IPv4的INADDR_ANY常值或IPv6的IN6ADDR_ANY_INIT常值等價的一個地址。注意:給UNIX域套接口bind的路徑名如果在文件系統(tǒng)
18、中已經(jīng)存在,則bind將失敗。為預(yù)防此種情況,可以先調(diào)用unlink。14.UNIX域套接口使用套接口函數(shù)的一些差別和限制下面是Posix.1g的一些要求,并不是所有的實現(xiàn)都做到了這一級:bind建立的路徑名的缺省訪問權(quán)限應(yīng)為0777,并被當(dāng)前的umask值修改;UNIX域套接口相關(guān)聯(lián)的路徑名應(yīng)為一個絕對路徑名,而不是相對路徑名;connect使用的路徑名必須是一個綁定在某個已打開的UNIX域套接口上的路徑名,而且套接口的類型(字節(jié)流或數(shù)據(jù)報)也必須一致;用connect連接UNIX域套接口時的權(quán)限檢查和用open以只寫方式訪問路徑名時完全相同;UNIX域字節(jié)流套接口和TCP套接口類似:他們都
19、為進程提供一個沒有記錄邊界的字節(jié)流接口;如果UNIX域字節(jié)流套接口的connect調(diào)用發(fā)現(xiàn)套接口的隊列已滿,會立即返回一個ECONNREFUSED錯誤,這和TCP有所不同;UNIX域數(shù)據(jù)報套接口和UDP套接口類似:都提供一個保留記錄邊界的不可靠的數(shù)據(jù)報服務(wù);與UDP套接口不同,在未綁定的UNIX域套接口上發(fā)送數(shù)據(jù)報不會給它捆綁一個路徑名。同樣,與TCP和UDP不同的是,個UNIX域數(shù)據(jù)報套接口調(diào)用connect不會捆綁一個路徑名。15.描述字傳遞機制使用UNIX域套接口可以在兩個沒有關(guān)系的進程之間傳遞描述字。4.4BSD的技術(shù)允許一次sendmsg傳遞多個描述字,而SVR4的技術(shù)一次只能傳遞一
20、個描述字。在兩個進程之間傳遞描述字的步驟如下:創(chuàng)建一個字節(jié)流或數(shù)據(jù)報的UNIX域套接口。如果兩進程有父子關(guān)系,可以使用socketpair,否則服務(wù)器必須創(chuàng)建一個UNIX域套接口,bind一個路徑名,讓客戶connect到這個套接口。進程可以用任何返回描述字UNIX函數(shù)打開一個描述字,如open、pipe、mkfifo、socket或accept。可以在進程之間傳遞任何類型的描述字。發(fā)送進程建立一個msghdr結(jié)構(gòu),其中包含要傳遞的描述字,Posix.1g說明該描述字作為輔助數(shù)據(jù)發(fā)送(msghdr結(jié)構(gòu)的msg_control或msg_accright成員),發(fā)送進程調(diào)用sendmsg通過第一步
21、得到的UNIX域套接口發(fā)出描述字。這時該描述字是在飛行中(in flight),即使sendmsg之后,在recvmsg之前將該描述字關(guān)閉,它仍會為接收進程保持打開狀態(tài)。描述字的發(fā)送導(dǎo)致它的訪問計數(shù)加1。接收進程調(diào)用recvmsg,在UNIX域套接口上接收描述字。通常接收進程收到的描述字的編號與發(fā)送進程中的描述字編號不同。C/S之間必須有某種應(yīng)用協(xié)議,使接收方知道何時接收描述字,如果接收方調(diào)用recvmsg但沒有分配接收描述字的空間,而且一個描述字已被傳遞并正待讀出,這個已傳遞的描述字就會關(guān)閉。在用recvmsg接收描述字時要避免使用MSG_PEEK標(biāo)志,否則后果不可預(yù)料。16.非阻塞套接口I
22、/O概述缺省狀態(tài)下,套接口是阻塞方式的,當(dāng)一個套接口調(diào)用不能立即完成時,進程進入睡眠狀態(tài),等待操作完成??赡茏枞奶捉涌谡{(diào)用分為如下四種:輸入操作:read、readv、recv、recvfrom和recvmsg函數(shù)。在一個非阻塞套接口上,如果輸入操作不能滿足,它們將會立即返回一個EWOULDBLOCK錯誤。輸出操作:write、writev、send、sendto和sendmsg函數(shù)。在一個非阻塞套接口上,如果發(fā)送緩沖區(qū)沒有空間,它們將會立即返回一個EWOULDBLOCK錯誤,如果發(fā)送緩沖區(qū)有一些空間,返回值為內(nèi)核能向緩沖區(qū)中拷貝的字節(jié)數(shù)(不足計數(shù)(short count)。接收外來連接:a
23、ccept函數(shù)。在非阻塞套接口上調(diào)用accept函數(shù),而且沒有新的連接,將返回EWOULDBLOCK錯誤。初始化外出的連接:用于TCP的connect函數(shù)。在非阻塞的套接口上調(diào)用connect,而且連接不能馬上建立,連接的建立過程將開始,但返回一個EINPROGRESS錯誤。也存在連接立即建立的情況。對于非阻塞I/O不能馬上完成返回的錯誤碼不同實現(xiàn)有差異:系統(tǒng)V返回EAGAIN,而Berkeley返回EWOULDBLOCK,幸好這兩個錯誤碼在多數(shù)實現(xiàn)中值相等。非阻塞connect非阻塞connect有如下三種用途:我們可以在三路握手的同時做一些其他的處理;可以用這種技術(shù)同時建立多個連接;我們用
24、select等待連接的完成,因此可以給select設(shè)置一個時間限制,從而縮短connect的超時時間。處理非阻塞connect有一些細節(jié)需要處理:即使套接口是非阻塞的,如果連接的服務(wù)器在同一臺主機上,在調(diào)用connect時連接通常會立刻建立。源自Berkeley的實現(xiàn)有兩條與select和非阻塞I/O相關(guān)的規(guī)則:(1)當(dāng)連接成功建立時,描述字變成可寫;(2)當(dāng)連接建立出錯時,描述字變成既可讀又可寫。非阻塞connect有許多移植性的問題,如getsockopt等,需要注意。被中斷的阻塞connect一個被中斷的阻塞connect不自動重啟的情況下,它會返回EINTR,此時我們不能再調(diào)用conn
25、ect等待連接建立完成,這樣做將返回EADDRINUSE錯誤。在這種情況下要做的是要么關(guān)閉套接口,重新調(diào)用socket和connect;要么調(diào)用select,和非阻塞connect一樣處理,使select在連接建立成功(使套接口可寫)或連接失敗(使套接口科可讀又可寫)時返回。非阻塞accept如前accept返回前連接夭折所述,在服務(wù)器調(diào)用accept之前客戶如果放棄這個連接,源自Berkeley的實現(xiàn)不對服務(wù)器返回這個夭折的連接,而其他實現(xiàn)應(yīng)返回ECONNABORTED錯誤,但一般返回EPROTO錯誤。如果在accept之前使用select來測試連接是否準備好,要注意的是在select和ac
26、cept之間如果連接夭折,源自Berkeley的實現(xiàn)會導(dǎo)致accept阻塞,直到其他某個客戶建立一個連接為止。所以使用select并不能保證accept不會阻塞。解決方法是:如果用select來獲取何時有連接已就緒可以accept時,總是把監(jiān)聽套接口設(shè)置為非阻塞的;并且在后面的accept中忽略以下錯誤:EWOULDBLOCK(源自Berkeley的實現(xiàn)在客戶放棄連接時出現(xiàn)的錯誤)、ECONNABORTED(Posix.1g的實現(xiàn)在客戶放棄連接時出現(xiàn)的錯誤)、EPROTO(SVR4的實現(xiàn)在客戶放棄連接時出現(xiàn)的錯誤)和EINTR(如果信號被捕獲)。17.服務(wù)器程序常見設(shè)計方法服務(wù)器程序設(shè)計方法列
27、出如下9種:迭代服務(wù)器(無進程控制);簡單并發(fā)服務(wù)器,每個客戶fork一次;預(yù)先派生子進程,每個子進程相互獨立調(diào)用accept;預(yù)先派生子進程,使用文件上鎖保護accept;預(yù)先派生子進程,使用線程互斥鎖上鎖保護accept;預(yù)先派生子進程,父進程向子進程傳遞套接口描述字;并發(fā)服務(wù)器,每個客戶請求創(chuàng)建一個線程;預(yù)先創(chuàng)建線程服務(wù)器,使用互斥鎖上鎖保護accept;預(yù)先創(chuàng)建線程服務(wù)器,由主線程調(diào)用accept。有如下結(jié)論:當(dāng)系統(tǒng)負載較輕時,傳統(tǒng)的并發(fā)服務(wù)器程序模型就夠了。相對于傳統(tǒng)的每個客戶一次fork設(shè)計,預(yù)先創(chuàng)建一個進程池或線程池可以減少進程控制CPU時間,大約可減少10倍以上。某些實現(xiàn)允許多
28、個子進程或線程阻塞在accept上,然而在另一些實現(xiàn)中,我們必須使用文件鎖、線程互斥鎖或其他類型的鎖來確保每次只有一個子進程或線程在accept。一般來將,所有子進程或線程都調(diào)用accept要比父進程或主線程調(diào)用accept后將描述字傳遞個子進程或線程來得快且簡單。由于select沖突的存在,讓所有子進程或線程阻塞在同一監(jiān)聽套接口的accept調(diào)用上要比讓它們阻塞在select調(diào)用上更為可取。使用線程通常比使用進程快。不過選擇每個客戶一個子進程還是每個客戶一個線程取決于操作系統(tǒng)提供什么以及需什么其他程序來服務(wù)各個客戶。18.注意網(wǎng)絡(luò)編程的移植性問題在winsock中套接口描述符用SOCKET而
29、不是int類型定義。盡量避免在套接口字上使用read和write函數(shù),因為在WIN32中不支持它們。我們一般用recv、recvfrom和recvmsg來表示讀,用send、sendto和sendmsg表示寫。19.注意對等方的不合理行為軟件應(yīng)編寫成能夠處理任何想象的到的錯誤,不管該錯誤可能發(fā)生的概率是如何的小。在網(wǎng)絡(luò)編程中,應(yīng)當(dāng)牢記的規(guī)則是:不能假設(shè)對等方會嚴格遵守應(yīng)用程序協(xié)議,甚至是在我們實現(xiàn)雙方協(xié)議的時候也是這樣。如在長鏈中檢查客戶端是否終止,檢查輸入的有效性,注意緩沖區(qū)的溢出和指針失控。20.開發(fā)和使用應(yīng)用程序框架大多數(shù)的TCP/IP應(yīng)用程序?qū)儆谙旅嫠姆N之一:TCP服務(wù)器、TCP客戶端
30、、UDP服務(wù)器、UDP客戶端。每類應(yīng)用程序都有類似的代碼來完成初始化工作,所以可以定義一些程序框架(模板)。使用時根據(jù)情況稍做修改即可。21.在應(yīng)用程序中中實現(xiàn)keep-alive機制當(dāng)應(yīng)用程序啟用TCP的keep-alive機制時,TCP就會在連接已經(jīng)空閑了一定時間間隔后發(fā)送一個特殊的段給對等方。如果對等方主機可以到達而且對等方應(yīng)用程序依然運行,對等方TCP就會響應(yīng)一個ACK應(yīng)答,此時通訊正常,TCP將發(fā)送keep-alive空閑時間重置為0,應(yīng)用程序不會接收到消息交換的任何通知。如果對等方主機可以到達,但對等方應(yīng)用程序沒有運行,則對等方TCP響應(yīng)RST,發(fā)送方的TCP撤消連接并返回ECON
31、NRESET錯誤給應(yīng)用程序。如果對等方主機沒有響應(yīng)ACK或RST消息,發(fā)送方TCP繼續(xù)發(fā)送keep-alive探詢消息,直到它認為對等方不可達到或已經(jīng)崩潰。此時撤消連接并通知應(yīng)用ETIMEDOUT錯誤。如果路由器已經(jīng)返回主機或網(wǎng)絡(luò)不可到達的ICMP消息的話,則返回EHOSTUNREACH或ENETUNREACH錯誤。TCP的keep-alive機制的問題是檢測的空閑時間太長(至少是2小時),而且它不僅檢測死連接,同時也撤消它們,有時這并不是應(yīng)用程序所期望的。可以在應(yīng)用程序中實現(xiàn)類似的機制來解決keep-alive的問題,通過編寫心博(heartbeat)函數(shù)。22.理解TCP的寫操作應(yīng)用程序?qū)?/p>
32、操作成功并不表示數(shù)據(jù)已經(jīng)發(fā)送到對等方。寫操作把數(shù)據(jù)放到發(fā)送緩沖區(qū)中,除非TCP發(fā)送緩沖區(qū)已滿,否則寫操作是不會阻塞的,這意味著寫操作幾乎總是立即返回,而且如果它返回了,也不能保證所寫數(shù)據(jù)的位置。實際上,當(dāng)寫操作返回時,寫入的部分或全部數(shù)據(jù)可能仍舊在排隊等待傳輸,如果此時對等方主機或應(yīng)用程序崩潰的話,數(shù)據(jù)將會丟失。因為寫操作可能在數(shù)據(jù)實際發(fā)送之前就已經(jīng)返回,所以當(dāng)傳輸發(fā)生錯誤時,該錯誤通常是從下一個操作返回。寫操作返回的錯誤僅僅是那些在調(diào)用寫操作時就已經(jīng)發(fā)生的錯誤,除了EPIPE錯誤。23.使應(yīng)用程序事件驅(qū)動利用select來實現(xiàn)一個通用的分時機制,允許在一定時間間隔后指定一個必須發(fā)生的事件,而
33、且使該事件在指定的時間上異步發(fā)生。24.不要試圖繞過TIME-WAIT狀態(tài)TIME-WAIT狀態(tài)是TCP可靠性中很重要的一部分,程序員不應(yīng)該試圖繞過它,雖然可以使用SO_LINGER套接口選項來取消它。25.服務(wù)器應(yīng)當(dāng)設(shè)置SO_REUSEADDR選項對于TCP服務(wù)器總是應(yīng)該設(shè)置SO_REUSEADDR選項,否則沒法重新啟動一個在TIME-WAIT狀態(tài)中還存在連接的服務(wù)器。該選項必須在bind()之前調(diào)用setsockopt()設(shè)置。26.盡量使用大型寫操作代替多個小規(guī)模寫操作使用大型寫操作的原因除了避免上下文切換外,主要目的是避免因過多的小規(guī)模寫操作導(dǎo)致Nagle算法的影響,從而對程序性能造成
34、極大的負面影響。雖然可以使用套接口選項TCP_NODELAY來禁止Nagle算法,但不是解決問題的方法。所以要減少小規(guī)模的寫操作,多次寫合并成一次寫。實現(xiàn)的一種方法是使用聚集寫:readv和writev。在Winsock中則使用不同但類似的接口:WSAsend。27.注意異步connect的可移植問題把connect設(shè)置為非阻塞的主要用途是使connect具有超時機制。使用select是實現(xiàn)的一種方法。但使用該法有比較多的可移植問題。程序的關(guān)鍵是在判斷連接是否成功的地方。下面是UNIX版本:int isconnected(SOCKET s,fd_set*rd,fd_set*wr,fd_set*ex)int err
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 專業(yè)地坪承包2024協(xié)議樣式版B版
- 2024年音響產(chǎn)品售后服務(wù)與維修合同
- 2024年飯店品牌授權(quán)加盟合同3篇
- 2024年輔導(dǎo)班教學(xué)服務(wù)合作合同版B版
- 2025年車輛租賃與廣告投放合作合同范本3篇
- 2024年革新版:無人機物流配送服務(wù)合同
- 2024氣象服務(wù)與航空航天器氣象保障合同范本3篇
- 2025年菜鳥驛站新能源汽車充電站運營權(quán)轉(zhuǎn)讓合同3篇
- 2025年度智能電網(wǎng)調(diào)度控制系統(tǒng)軟件開發(fā)框架合同3篇
- 《換能器技術(shù)》課件
- 2024年《論教育》全文課件
- 浙江省溫州市鹿城區(qū)2023-2024學(xué)年三年級上學(xué)期期末數(shù)學(xué)試卷
- (正式版)SHT 3158-2024 石油化工管殼式余熱鍋爐
- 一年級口算天天練(可直接打印)
- 小學(xué)數(shù)學(xué)專題講座:小學(xué)數(shù)學(xué)計算能力的培養(yǎng)課件
- PPT預(yù)制小箱梁施工技術(shù)
- 河北省滄州市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會明細
- 精品電力工程質(zhì)量目標(biāo)、質(zhì)量保證體系及技術(shù)組織措施
- 高考物理知識歸納總結(jié)之六(磁場、電磁感應(yīng)和交流電)
- 檳榔黃化病的診斷及防控
- 眼外傷-PPT課件
評論
0/150
提交評論