socket 选项 详细说明
下面的兩個函數主要是用于設置socket文件描述符屬性的方法
getsockopt 和setsockopt這兩個函數成功時返回0,失敗時返回-1并設置errno ,可以使用 strerror(errno) 將錯誤碼轉換為對應的提示消息。
例子如下
/*查詢和設置接收緩沖區*/ int recvbuf = 0; int len = sizeof( recvbuf ); getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len); DC_INFO( "the receive buffer size before settting is %d", recvbuf );recvbuf = size; if(0 != setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf) )) {DC_ERROR("setsockopt SO_RCVBUF error ,errmsg = %s",strerror(errno));return SERVER_ERROR; }下面進行一些詳細介紹
1.對于服務器而言,有部分socket選項只能在listen前針對監聽socket設置才有效!這是因為連接socket只能由accept調用返回,而accept從listen監聽隊列中接受的連接至少已經完成了TCP三次握手的前兩個步驟(因為listen監聽隊列中的連接至少已進入SYN_RCVD狀態),這說明服務器已經往被接收連接上發出了TCP同步報文段。但有的socket選項卻應該在TCP同步報文段中設置,比如TCP最大報文選項!對應的解決方案是:對監聽socket設置這些socket選項,那么accept返回的連接socket將自動繼承這些選項!
? 這些選項包括SO_DEBUG,SO_DONTROUTE,SO_LINGER,SO_OOBINLINE,SO_RCVBUF,SO_RCVLOWAT,SO_SNDBUF,SO_SNDLOWAT,TCP_MAXSEG和TCP_NODELAY。而對于客戶端而言,這些socket必須在connect之前設置,因為connect調用成功之后 tcp的三次握手已經完成了!
2.SO_REUSEADDR選項
tcp服務器連接的TIME_WAIT狀態,可以通過設置該選項是的綁定的socket地址立即被重用!
此外還有個另外的方式,修改內核參數 /proc/sys/net/ipv4/tcp_tw_recycle 來快速回收被關閉的socket ,從而使得tcp連接國標不會進入TIME_WAIT狀態,進而使得程序可以立即重用本地的socket地址!
3.SO_RCVBUF 和SO_SNDBUF
這兩個選項分別表示TCP接收緩沖區和發送緩沖區的大小!
不過當我們通過setsockopt來設置tcp的接受和發送緩沖區大小的時候,系統會將其值加倍,并且不得小于某個最小值,同時也不得超過最大值!不過每個系統值可能有不同的默認值!
此外我們還可以直接修改內核參數?/proc/sys/net/ipv4/tcp_rmem 和/proc/sys/net/ipv4/tcp_wmem 來強制修改tcp接收和發送緩沖區的限制!
代碼如下
int SocketServer::make_socket_buffsize(int sock,int size) {/*查詢和設置接收緩沖區*/int recvbuf = 0;int len = sizeof( recvbuf );getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);DC_INFO( "the receive buffer size before settting is %d", recvbuf );recvbuf = size;if(0 != setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf) )){DC_ERROR("setsockopt SO_RCVBUF error ,errmsg = %s",strerror(errno));return SERVER_ERROR;}getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);DC_INFO( "the receive buffer size after settting is %d", recvbuf );/*查詢和設置發送緩沖區*/int sendbuf = 0;getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len);DC_INFO( "the tcp send buffer size before setting is %d", sendbuf );sendbuf = size;if(0 != setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf) )){DC_ERROR("setsockopt SO_SNDBUF error ,errmsg = %s",strerror(errno));return SERVER_ERROR;}getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len);DC_INFO( "the tcp send buffer size after setting is %d", sendbuf );return SERVER_OK; }設置之后的最大值一般就是默認一次可以讀取的字節數!
4.SO_RCVLOWAT 和SO_SNDLOWAT 選項
這兩個選項分別表示tcp接受和發送緩沖區的低水位標志。它們一般被I/O復用系統調用來判斷socket是否可讀或可寫。
當tcp接收緩沖區中可讀數據的總數大于低水位標記時,I/O系統調用將通知應用程序可以從對于的socket讀取數據,當TCP發送緩沖區中的空閑空間大于其低水位,將通知應用程序可以往對應的socket上寫數據。
默認情況下,這兩個選項均為1字節!
5.SO_LINGER?
此選項指定函數close對面向連接的協議如何操作(如TCP)。內核缺省close操作是立即返回,如果有數據殘留在套接口緩沖區中則系統將試著將這些數據發送給對方。
1、設置 l_onoff為0,則該選項關閉,l_linger的值被忽略,等于內核缺省情況,close調用會立即返回給調用者,如果可能將會傳輸任何未發送的數據;
2、設置 l_onoff為非0,l_linger為0,close系統調用立即返回,TCP將丟棄保留在套接口發送緩沖區中的任何數據并發送一個RST給對方。
3、設置 l_onoff 為非0,l_linger為非0,此時的close的行為取決兩個條件:一是被關閉的socket對應的TCP發送緩沖區是否還有殘留的數據;二是該socket是阻塞的還是非阻塞的。對于阻塞的socket,close將等到l_linge的時間,直到tcp模塊發送完所有殘留數據并得到對方的確認。如果這段時間tcp沒有發送完殘留的數據,那么close將返回-1,并將errno設置為EWOULDBLOCK。如果該socket是非阻塞的,close將立即返回,此時我們需要根據返回值和errno來判斷殘留數據是否已經發送完畢!
總結
以上是生活随笔為你收集整理的socket 选项 详细说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第四百一十七天 how can I 坚持
- 下一篇: SQL SELECT DISTINCT