1. 程式人生 > >inux c學習筆記----SCTP基礎客戶/服務程式設計(setsockopt,sctp_sendmsg等)

inux c學習筆記----SCTP基礎客戶/服務程式設計(setsockopt,sctp_sendmsg等)

在程式設計之前先了解一下sctp套接字選項

setsockopt(設定socket狀態)

相關函式 getsockopt
表頭檔案 #include<sys/types.h>
#include<sys/socket.h>
定義函式 int setsockopt(int s,int level,int optname,const void * optval,,socklen_toptlen);
函式說明 setsockopt()用來設定引數s所指定的socket狀態。引數level代表欲設定的網路層,一般設成SOL_SOCKET以存取socket層。引數optname代表欲設定的選項,有下列幾種數值:
SO_DEBUG 開啟或關閉排錯模式
SO_REUSEADDR 允許在bind()過程中本地地址可重複使用
SO_TYPE 返回socket形態。
SO_ERROR 返回socket已發生的錯誤原因
SO_DONTROUTE 送出的資料包不要利用路由裝置來傳輸。
SO_BROADCAST 使用廣播方式傳送
SO_SNDBUF 設定送出的暫存區大小
SO_RCVBUF 設定接收的暫存區大小
SO_KEEPALIVE 定期確定連線是否已終止。
SO_OOBINLINE 當接收到OOB 資料時會馬上送至標準輸入裝置
SO_LINGER 確保資料安全且可靠的傳送出去。
引數 optval代表欲設定的值,引數optlen則為optval的長度。
返回值 成功則返回0,若有錯誤則返回-1,錯誤原因存於errno。
附加說明 EBADF 引數s並非合法的socket處理程式碼
ENOTSOCK 引數s為一檔案描述詞,非socket
ENOPROTOOPT 引數optname指定的選項不正確。
EFAULT 引數optval指標指向無法存取的記憶體空間。

設定 sctp時level為IPPROTO_SCTP,optname即為sctp套接字選項

這裡只介紹SCTP_INITMSG選項:

本套接字選項用於獲取或設定某個SCTP套接字在傳送INIT訊息時所用的預設初始引數。作為本選項的輸入的是sctp_initmsg結構(即為setsockopt函式的第五個引數)。其定義如下:

struct sctp_initmsg{

      uint16_t sinit_num_ostream;

      uint16_t sinit_max_instream;

      unit16_t sinit_max_attempts;

      unit16_t sinit_max_init_timeo;

}

這些欄位的含義如下:

sinit_num_ostream表示應用程序想要請求的外出sctp流的數目。該值要等到相應關聯完成初始握手後才得到確認,而且可能因為對端的限制而向下協調。

sinit_max_instream

表示應用程序準備允許的外來SCTP流的最大數目。如果該值大於SCTP協議棧支援的最大允許流數,那麼它將被為這個最大數。

sinit_max_attempts表示SCTP協議棧應該重傳多少次初始INIT訊息才認為對端不可達。

sinit_max_init_timeo表示用於INIT定時器的最大RTO值。在初始定時器進行指數退避期間,該值將替代RTO.max作為重傳RTO極限。該值以毫秒為單位。

注意:當設定這些欄位時,SCTP將忽略其中的任何0值。一到多式套接字的使用者在關聯隱性建立期間也可能在輔助資料中傳遞一個sctp_initmsg結構。

SCTP 套接字介面

當 socket() 呼叫為 IPPROTO_SCTP 建立套接字時,它會呼叫特定於 SCTP 的套接字建立例程。針對 SCTP 套接字執行的套接字呼叫會自動呼叫相應的 SCTP 套接字例程。在一對一套接字中,每個套接字都對應一個 SCTP 關聯。可以通過呼叫以下函式來建立一對一套接字:

socket(AF_INET[6], SOCK_STREAM, IPPROTO_STCP); 

在一對多風格套接字中,每個套接字都處理多個 SCTP 關聯。每個關聯都具有一個名為 sctp_assoc_t 的關聯識別符號。可以通過呼叫以下函式來建立一對多套接字:

socket(AF_INET[6], SOCK_SEQPACKET, IPPROTO_STCP); 

sctp_bindx()

int sctp_bindx(int sock, void *addrs, int addrcnt, int flags); 

sctp_bindx() 函式管理 SCTP 套接字上的地址。如果 sock 引數為 IPv4 套接字,則傳送給 sctp_bindx() 函式的地址必須為 IPv4 地址。如果 sock 引數為 IPv6 套接字,則傳送給 sctp_bindx() 函式的地址可以為 IPv4 或 IPv6 地址。當傳送給 sctp_bindx() 函式的地址為INADDR_ANY 或 IN6ADDR_ANY 時,此套接字將繫結到所有可用地址。可以使用 bind(3SOCKET) 繫結 SCTP 端點。

*addrs 引數的值是指向包含一個或多個套接字地址的陣列的指標。每個地址都包含在其相應的結構中。如果地址為 IPv4 地址,則它們可以包含在sockaddr_in 結構或 sockaddr_in6 結構中。如果地址為 IPv6 地址,則它們可以包含在 sockaddr_in6 結構中。可以通過地址型別系列區分地址長度。呼叫方使用 addrcnt 引數指定陣列中的地址數。

如果成功,則 sctp_bindx() 函式將返回 0。如果失敗,則 sctp_bindx() 函式將返回 -1,並將 errno 的值設定為相應的錯誤程式碼。

如果沒有為每個套接字地址提供同一埠,則 sctp_bindx() 函式將失敗,並將 errno 的值設定為 EINVAL

通過對以下零個或多個當前定義的標誌執行按位 OR 運算,即可形成 flags 引數:

  • SCTP_BINDX_ADD_ADDR

  • SCTP_BINDX_REM_ADDR

SCTP_BINDX_ADD_ADDR 指示 SCTP 將給定地址新增到關聯中。SCTP_BINDX_REM_ADDR 指示 SCTP 從關聯中刪除給定地址。這兩個標誌相互排斥。如果同時提供這兩個標誌,則 sctp_bindx() 將失敗,並將 errno 的值設定為 EINVAL

呼叫方無法刪除關聯中的所有地址。sctp_bindx() 函式拒絕此類嘗試的表現為:函式失敗並將 errno 的值設定為 EINVAL。應用程式可以在呼叫 bind() 函式之後使用 sctp_bindx(SCTP_BINDX_ADD_ADDR),將其他地址與端點關聯。應用程式可以使用sctp_bindx(SCTP_BINDX_REM_ADDR) 刪除與偵聽套接字關聯的地址。使用 sctp_bindx(SCTP_BINDX_REM_ADDR) 刪除地址之後,接受新關聯將不會重新關聯已刪除的地址。如果端點支援動態地址,則可以使用 SCTP_BINDX_REM_ADDR 或 SCTP_BINDX_ADD_ADDR 向對等方傳送訊息來更改對等方的地址列表。在已連線的關聯中新增和刪除地址為可選功能。不支援此功能的實現將返回 EOPNOTSUPP

如果地址族不是 AF_INET 或 AF_INET6,則 sctp_bindx() 函式將失敗並返回 EAFNOSUPPORT。如果 sock 引數中傳遞給 sctp_bindx() 的檔案描述符無效,則 sctp_bindx() 函式將失敗並返回 EBADF

sctp_opt_info()

int sctp_opt_info(int sock, sctp_assoc_id_t id, int opt, void *arg, socklen_t *len); 

sctp_opt_info() 函式將返回與 sock 引數中所述的套接字關聯的 SCTP 級別選項。如果此套接字為一對多風格 SCTP 套接字,則 id 引數的值是某個特定關聯。對於一對一風格 SCTP 套接字,將忽略 id 引數。opt 引數的值指定要獲取的 SCTP 套接字選項。arg 引數的值是為呼叫程式而分配的特定於選項的結構緩衝區。*len 引數的值為選項長度。

opt 引數可以採用以下值:

SCTP_RTOINFO

返回用於初始化和繫結重新傳輸超時 (retransmission timeout, RTO) 可調引數的協議引數。這些協議引數使用以下結構:

struct sctp_rtoinfo {

       sctp_assoc_t srto_assoc_id;

       uint32_t     srto_initial;

       uint32_t     srto_max; 

       uint32_t     srto_min;

};
srto_assoc_id

呼叫程式提供此值,它指定所關注的關聯。

srto_initial

此值為初始 RTO 值。

srto_max

此值為最大 RTO 值。

srto_min

此值為最小 RTO 值。

SCTP_ASSOCINFO

返回特定於關聯的引數。這些引數使用以下結構:

struct sctp_assocparams {

     sctp_assoc_t sasoc_assoc_id;

     uint16_t     sasoc_asocmaxrxt;

     uint16_t     sasoc_number_peer_destinations;

     uint32_t     sasoc_peer_rwnd;

     uint32_t     sasoc_local_rwnd;

     uint32_t     sasoc_cookie_life;

};
sasoc_assoc_id

呼叫程式提供此值,它指定所關注的關聯。

sasoc_assocmaxrxt

此值指定關聯的最大重新傳輸計數。

sasoc_number_peer_destinations

此值指定對等方具有的地址數。

sasoc_peer_rwnd

此值指定對等方接收視窗的當前值。

sasoc_local_rwnd

此值指定對等方傳輸到的上一個已報告的接收視窗。

sasoc_cookie_life

此值指定關聯 cookie 的生命週期。可在發出 cookie 時使用此值。

所有使用時間值的引數均以毫秒為單位。

SCTP_DEFAULT_SEND_PARAM

返回 sendto(3SOCKET) 函式呼叫在此關聯中使用的預設引數集。這些引數使用以下結構:

struct sctp_sndrcvinfo {

     uint16_t     sinfo_stream;

     uint16_t     sinfo_ssn;

     uint16_t     sinfo_flags;

     uint32_t     sinfo_ppid;

     uint32_t     sinfo_context;

     uint32_t     sinfo_timetolive;

     uint32_t     sinfo_tsn;

     uint32_t     sinfo_cumtsn;

     sctp_assoc_t sinfo_assoc_id;

};
sinfo_stream

此值指定 sendmsg() 呼叫的預設流。

sinfo_ssn

此值始終為 0。

sinfo_flags

此值包含 sendmsg() 呼叫的預設標誌。此標誌可以採用以下值:

  • MSG_UNORDERED

  • MSG_ADDR_OVER

  • MSG_ABORT

  • MSG_EOF

  • MSG_PR_SCTP

sinfo_ppid

此值為 sendmsg() 呼叫的預設有效負荷協議識別符號。

sinfo_context

此值為 sendmsg() 呼叫的預設上下文。

sinfo_timetolive

此值指定時間段(以毫秒為單位)。在此時間段過後,如果訊息傳輸尚未開始,則訊息將過期。值為 0 指示訊息尚未過期。如果設定了MSG_PR_SCTP 標誌,當訊息傳輸未在 sinfo_timetolive 所指定的時間段內成功完成時,訊息將過期。

sinfo_tsn

此值始終為 0。

sinfo_cumtsn

此值始終為 0。

sinfo_assoc_id

此值由呼叫程式填充。它指定所關注的關聯。

SCTP_PEER_ADDR_PARAMS

返回所指定對等地址的引數。這些引數使用以下結構:

struct sctp_paddrparams {

     sctp_assoc_t            spp_assoc_id;

     struct sockaddr_storage spp_address;

     uint32_t                spp_hbinterval;

     uint16_t                spp_pathmaxrxt;

};
spp_assoc_id

呼叫程式提供此值,它指定所關注的關聯。

spp_address

此值指定所關注的對等地址。

spp_hbinterval

此值指定心跳間隔(以毫秒為單位)。

spp_pathmaxrxt

此值指定在認為地址不可訪問之前針對此地址嘗試的最大重新傳輸數。

SCTP_STATUS

返回有關關聯的當前狀態資訊。這些引數使用以下結構:

struct sctp_status {

     sctp_assoc_t          sstat_assoc_id;

     int32_t               sstat_state;

     uint32_t              sstat_rwnd;

     uint16_t              sstat_unackdata;

     uint16_t              sstat_penddata;

     uint16_t              sstat_instrms;

     uint16_t              sstat_outstrms;

     uint32_t              sstat_fragmentation_point;

     struct sctp_paddrinfo sstat_primary;

};
sstat_assoc_id

呼叫程式提供此值,它指定所關注的關聯。

sstat_state

此值為關聯的當前狀態。關聯可以採用以下狀態:

SCTP_IDLE

SCTP 端點沒有任何與其關聯的關聯。一旦 socket() 函式呼叫開啟一個端點或端點關閉,則端點便會處於此狀態。

SCTP_BOUND

SCTP 端點在呼叫 bind() 之後繫結到一個或多個本地地址。

SCTP_LISTEN

此端點在等待來自任何遠端 SCTP 端點的關聯請求。

SCTP_COOKIE_WAIT

此 SCTP 端點已傳送 INIT 塊並在等待 INIT-ACK 塊。

SCTP_COOKIE_ECHOED

此 SCTP 端點已將從其對等方的 INIT-ACK 塊接收的 cookie 回顯到對等方。

SCTP_ESTABLISHED

此 SCTP 端點可以與其對等方交換資料。

SCTP_SHUTDOWN_PENDING

此 SCTP 端點已從其上層接收了 SHUTDOWN 元語。此端點不再從其上層接受資料。

SCTP_SHUTDOWN_SEND

處於 SCTP_SHUTDOWN_PENDING 狀態的 SCTP 端點已向其對等方傳送了 SHUTDOWN 塊。僅在確認所有從此端點到其對等方的未完成資料之後,才傳送 SHUTDOWN 塊。當此端點的對等方傳送 SHUTDOWN ACK 塊時,此端點會發送 SHUTDOWN COMPLETE 塊並認為關聯已關閉。

SCTP_SHUTDOWN_RECEIVED

SCTP 端點已從其對等方接收了 SHUTDOWN 塊。此端點不再從其使用者接受新資料。

SCTP_SHUTDOWN_ACK_SEND

處於 SCTP_SHUTDOWN_RECEIVED 狀態的 SCTP 端點已向其對等方傳送了 SHUTDOWN ACK 塊。此端點僅在其對等方確認來自此端點的所有未完成資料之後傳送 SHUTDOWN ACK 塊。當此端點的對等方傳送 SHUTDOWN COMPLETE 塊時,將關閉關聯。

sstat_rwnd

此值為關聯對等方的當前接收視窗。

sstat_unackdata

此值為未確認的 DATA 塊數。

sstat_penddata

此值為等待接收的 DATA 塊數。

sstat_instrms

此值為傳入的流數。

sstat_outstrms

此值為外發的流數。

sstat_fragmentation_point

如果訊息、SCTP 資料包頭和 IP 資料包頭的組合大小超出 sstat_fragmentation_point 的值,則訊息會分段。此值等於包目標地址的路徑最大傳輸單元 (Path Maximum Transmission Unit, P-MTU)。

sstat_primary

此值包含有關主要對等地址的資訊。此資訊使用以下結構:

struct sctp_paddrinfo {

     sctp_assoc_t            spinfo_assoc_id;

     struct sockaddr_storage spinfo_address;

     int32_t                 spinfo_state;

     uint32_t                spinfo_cwnd;

     uint32_t                spinfo_srtt;

     uint32_t                spinfo_rto;

     uint32_t                spinfo_mtu;

};
spinfo_assoc_id

呼叫程式提供此值,它指定所關注的關聯。

spinfo_address

此值為主要對等地址。

spinfo_state

此值可以採用 SCTP_ACTIVE 或 SCTP_INACTIVE 兩個值中的任意一個。

spinfo_cwnd

此值為對等地址的擁塞視窗。

spinfo_srtt

此值為對等地址的當前平滑往返時間計算結果,以毫秒為單位。

spinfo_rto

此值為對等地址的當前重新傳輸超時值,以毫秒為單位。

spinfo_mtu

此值為對等地址的 P-MTU。

如果成功,則 sctp_opt_info() 函式將返回 0。如果失敗,則 sctp_opt_info() 函式將返回 -1,並將 errno 的值設定為相應的錯誤程式碼。如果 sock 引數中傳遞給 sctp_opt_info() 的檔案描述符無效,則 sctp_opt_info() 函式將失敗並返回 EBADF。如果 sock 引數中傳遞給 sctp_opt_info() 函式的檔案描述符沒有描述套接字,則 sctp_opt_info() 函式將失敗並返回 ENOTSOCK。如果關聯 ID 對於一對多風格 SCTP 套接字而言無效,則 sctp_opt_info() 函式將失敗,並將 errno 的值設定為 EINVAL。如果輸入緩衝區長度對於指定的選項而言過短,則 sctp_opt_info() 函式將失敗,並將 errno 的值設定為 EINVAL。如果對等地址的地址族不是 AF_INET 或 AF_INET6,則sctp_opt_info() 函式將失敗,並將 errno 的值設定為 EAFNOSUPPORT

sctp_recvmsg()

ssize_t sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from, socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo, int *msg_flags);