歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux套接字編程之套接字選項

套接字機制提供了兩個套接字選項接口來控制套接字的行為。一個接口用來設置選項,另外一個接口用來允許我們請求選項的狀態。我們可以獲得以及設置三種類型的選項。

1.通用選項,可以工作在所有的套接字類型。

2.在套接字層次上面進行管理的選項,但是依賴底部協議的支持。

3.和每個協議相關的協議選項。

Single UNIX Specification 只定義了套接字層的選項(上面所提到的前面兩項)

我們可以通過setsockopt函數來設置套接字選項。

#include <sys/socket.h>

int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len);

返回:如果成功返回0,如果錯誤返回1。

參數level用來分辨option所應用的協議。如果option是通用套接字層次的選項,那麼level設置成SOL_SOCKET。否則level設置成控制option的協議號。例如IPPROTO_TCP用於TCP選項,以及IPPROTO_IP用於IP選項。下面的表中就列出了Single UNIX Specification定義的通用的套接字層次的選項。

     套接字選項

+-------------------------------------------------------------------------------------------------------------+

|    Option     | Type of val argument |                             Description                              |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_ACCEPTCONN | int                  | 返回套接字是否激活用於偵聽(只用於getsockopt)。                     |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_BROADCAST  | int                  | 如果*val非0那麼廣播數據報。                                          |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_DEBUG      | int                  | 如果*val非0那麼激活網絡驅動的調試。                                  |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_DONTROUTE  | int                  | 如果*val非0,那麼忽略通常的路由。                                    |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_ERROR      | int                  | 返回並且清除提交的套接字錯誤(只用於getsockopt)。                   |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_KEEPALIVE  | int                  | 如果*val非0,那麼激活定期活動的消息。                                |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_LINGER     | struct linger        | 如果有未發送的消息存在以及套接字關閉,那麼做延遲。                   |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_OOBINLINE  | int                  | 如果*val非0,那麼將帶外數據嵌入到正常數據中。                        |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_RCVBUF     | int                  | 接收緩存的字節大小。                                                 |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_RCVLOWAT   | int                  | receive調用返回的最小數據字節。                                      |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_RCVTIMEO   | struct timeval       | 套接字receive調用的超時值。                                          |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_REUSEADDR  | int                  | 如果*val非0,那麼重復使用bind的地址。                                |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_SNDBUF     | int                  | send緩存中的字節大小。                                               |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_SNDLOWAT   | int                  | 一次send調用傳輸的最小數據字節量。                                   |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_SNDTIMEO   | struct timeval       | 一個套接字send調用的超時值。                                         |

|---------------+----------------------+----------------------------------------------------------------------|

| SO_TYPE       | int                  | 辨別套接字類型(只在getsockopt中)。                                 |

+-------------------------------------------------------------------------------------------------------------+

參數val指向一個數據結構或者整數,這取決於option。有些選項是on/off開關。 如果這個整數非0,那麼option被激活。如果這個整數是0,那麼option不被激活。len參數指定val指向的對象的大小。

我們可以通過函數getsockopt來獲取當前option的值。

#include <sys/socket.h>

int getsockopt(int sockfd, int level, int option, void *restrict val, socklen_t *restrict lenp);

返回:如果成功返回0,如果錯誤返回1。

注意lenp參數是一個指向整數的指針。在調用getsockopt之前,我們設置整數為option被拷貝的緩存的大小,如果實際的option大小比這個大小大,那麼option就會被截斷。如果實際的option大小比size小或者同樣大,那麼整數會在返回的時候被更新成實際的大小。

例子

前面的(initserver)函數當服務進程終止的時候操作失敗,然後我們嘗試立即重新啟動。一般來說,TCP的實現會會阻止我們將同樣一個地址綁定,除非超時。SO_REUSEADDR的套接字選項允許我們忽略這個限制,下面的代碼就展示了這個特性。

為了激活SO_REUSEADDR選項,我們設置整數為一個非0的值然後將整數的地址做為val參數傳遞給setsockopt函數。我們設置len參數為一個表示整數的大小,來表示val所指向的對象的大小。

服務進程使用地址重用初始化一個將要被使用的套接字末端

#include "apue.h"  
 #include <errno.h>  
 #include <sys/socket.h>  
 int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen)  
 {  
     int fd, err;  
     int reuse = 1;  
     if ((fd = socket(addr->sa_family, type, 0)) < 0)  
         return(-1);  
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {  
         err = errno;  
         goto errout;  
     }  
     if (bind(fd, addr, alen) < 0) {  
         err = errno;  
         goto errout;  
     }  
     if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {  
         if (listen(fd, qlen) < 0) {  
             err = errno;  
             goto errout;  
         }  
     }  
     return(fd);  
 errout:  
     close(fd);  
     errno = err;  
     return(-1);  
 }
Copyright © Linux教程網 All Rights Reserved