在linux之socket程式設計:網路程式設計基礎中介紹了socket程式設計中的一些框架性函式。可以保證網路資料能夠正常地到達使用者,這篇部落格主要講解網路通訊資料的互動,即網路資料的收發以及io模型。
這些函式中flags的值有如下,可以是單獨的乙個值也可以是按位或生成的復合值#include
#include
ssize_t send
(int sockfd,
const
void
*buf, size_t len,
int flags)
; ssize_t sendto
(int sockfd,
const
void
*buf, size_t len,
int flags,
const
struct sockaddr *dest_addr, socklen_t addrlen)
; ssize_t sendmsg
(int sockfd,
const
struct msghdr *msg,
int flags)
; ssize_t recv
(int sockfd,
void
*buf, size_t len,
int flags)
; ssize_t recvfrom
(int sockfd,
void
*buf, size_t len,
int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
; ssize_t recvmsg
(int sockfd,
struct msghdr *msg,
int flags)
;#include
ssize_t readv
(int fd,
const
struct iovec *iov,
int iovcnt)
; ssize_t writev
(int fd,
const
struct iovec *iov,
int iovcnt)
;
這幾個函式都可用於接收多個緩衝區資料。其中readv和writev直接在引數中指定緩衝區向量vector的個數,其中vector是一組vector向量的陣列。其資料結構定義如下:
在使用中需要指定iovec的iov_base的長度,值存放在iov_len中。struct iovec
;
而在recvmsg和sendmsg中的引數更為複雜,struct msghdr定義如下:
io的方式有阻塞io、非阻塞io、io復用、訊號驅動、非同步io等。其中阻塞io是最通用的io型別,使用這個模型進行資料接收的時候,在資料沒有到達之前程式會一直等待。而非阻塞io,則對每次請求,核心都不會阻塞,無論是否有資料到達都會立即返回。struct msghdr
;
使用io復用模型可以在等待的時候加入超時時間,當超時時間沒有到達的時候與阻塞的情況一致,而當超市時間到達仍然沒有資料接收到,會返回不再等待。流程如下:
其中函式有select和poll函式。
其中readfds、writefds、exceptfds分別為我們關心的是否可讀、可寫、異常的檔案描述符集,不關心的可以設定為null。在linux中fd_set是乙個很大的位元組陣列,其中每個檔案描述符都只占用一位(描述符0占用第0位…)。可以使用fd_clr把檔案描述符fd相應的位清零,使用fd_set把檔案描述符fd相對應的位置位,而使用fd_zero把檔案描述符集中的所有位都清0,fd_isset用來檢測檔案描述符fd在檔案描述符集中是否置位。nfds引數是這三個檔案描述集中最大檔案描述符的值加1,這個數其實是告訴核心我們所關心的描述符的範圍,可以使用fd_setsize(1024),但是這會浪費資源。最後乙個引數便是超時時間的設定。#include
/* according to earlier standards */
#include
#include
#include
intselect
(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout)
;void
fd_clr
(int fd, fd_set *set)
;int
fd_isset
(int fd, fd_set *set)
;void
fd_set
(int fd, fd_set *set)
;void
fd_zero
(fd_set *set)
;
select函式的返回值有三種:返回-1,表示發生了錯誤,在監聽的時候發生捕捉到了訊號;返回0,表示超時;返回乙個正數,表示有檔案已經就緒了,這時需要使用fd_isset來判斷是哪個檔案準備好了。select函式返回時會把沒有滿足條件的檔案描述符fd對應的位清零,所以再次使用時需要重新新增。
io復用中還有乙個poll函式也可以實現相同的功能,其中poll不是為每個條件構造乙個描述符集,而是構造乙個pollfd結構的陣列,每個成員指定乙個描述符編號以及我們對該描述符感興趣的條件。超時時間是以毫秒為單位。返回值的情況和select一致。第二個引數是pollfd的個數。
由於select和poll函式會受到訊號的影響,所以可以使用pselect和ppoll這兩個函式來遮蔽訊號的影響,從而避免函式執行過程中受訊號的干擾。#include
intpoll
(struct pollfd *fds, nfds_t nfds,
int timeout)
;struct pollfd
;
前幾種io模式我們過於被動,復用io也是需要等待一段時間(實質是輪詢檢視)。這裡可以使用非同步io,在我們所關心的條件滿足後,通過訊號來通知。這樣就不需要進行過多的等待了。原理如圖:
在linux中非同步io訊號是sigio和sigurg的組合,其中sigio是通用非同步io訊號,而sigurg則只用來通知程序網路連線上的帶外資料已經到達。
為了接收到非同步io訊號,需要執行以下3步:
LINUX程式設計 socket程式設計
什麼是套接字 套接字是一種通訊過程,它使客戶 伺服器系統的開發工作既可以在本地單機上進行,也可以跨網路進行。套接字建立過程 1,建立乙個套接字,這是分配給該伺服器程序的乙個作業系統資源,套接字由伺服器通過系統呼叫socket建立出來的,所以其它程序將不能對它進行訪問。2,給套接字起個名字,用系統呼叫...
SOCKET程式設計(LINUX)
現在的網路程式設計幾乎都是用的socket 本地的程序間通訊 ipc 有很多種方式,但可以總結為下面4類 2.我們要討論的是網路中程序之間如何通訊?在本地可以通過程序pid來唯一標識乙個程序,但是在網路中這是行不通的。三元組 ip位址,協議,埠 就可以標識網路的程序了,網路中的程序通訊就可以利用這個...
Linux程式設計基礎 Socket程式設計
linux下的socket程式設計大體上包括tcp socket udp socket即raw socket這三種,其中tcp和udp方式的socket程式設計用於編寫應用層的socket程式,是我們用得比較多的,而raw socket則用得相對較少,不在本文介紹範圍之列。tcp socket 基於...