Linux之socket程式設計 資料IO和復用

2021-10-04 16:15:55 字數 3507 閱讀 6599

在linux之socket程式設計:網路程式設計基礎中介紹了socket程式設計中的一些框架性函式。可以保證網路資料能夠正常地到達使用者,這篇部落格主要講解網路通訊資料的互動,即網路資料的收發以及io模型。

#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)

;

這些函式中flags的值有如下,可以是單獨的乙個值也可以是按位或生成的復合值

這幾個函式都可用於接收多個緩衝區資料。其中readv和writev直接在引數中指定緩衝區向量vector的個數,其中vector是一組vector向量的陣列。其資料結構定義如下:

struct iovec 

;

在使用中需要指定iovec的iov_base的長度,值存放在iov_len中。

而在recvmsg和sendmsg中的引數更為複雜,struct msghdr定義如下:

struct msghdr 

;

io的方式有阻塞io、非阻塞io、io復用、訊號驅動、非同步io等。其中阻塞io是最通用的io型別,使用這個模型進行資料接收的時候,在資料沒有到達之前程式會一直等待。而非阻塞io,則對每次請求,核心都不會阻塞,無論是否有資料到達都會立即返回。

使用io復用模型可以在等待的時候加入超時時間,當超時時間沒有到達的時候與阻塞的情況一致,而當超市時間到達仍然沒有資料接收到,會返回不再等待。流程如下:

其中函式有select和poll函式。

#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)

;

其中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),但是這會浪費資源。最後乙個引數便是超時時間的設定。

select函式的返回值有三種:返回-1,表示發生了錯誤,在監聽的時候發生捕捉到了訊號;返回0,表示超時;返回乙個正數,表示有檔案已經就緒了,這時需要使用fd_isset來判斷是哪個檔案準備好了。select函式返回時會把沒有滿足條件的檔案描述符fd對應的位清零,所以再次使用時需要重新新增

io復用中還有乙個poll函式也可以實現相同的功能,其中poll不是為每個條件構造乙個描述符集,而是構造乙個pollfd結構的陣列,每個成員指定乙個描述符編號以及我們對該描述符感興趣的條件。超時時間是以毫秒為單位。返回值的情況和select一致。第二個引數是pollfd的個數。

#include

intpoll

(struct pollfd *fds, nfds_t nfds,

int timeout)

;struct pollfd

;

由於select和poll函式會受到訊號的影響,所以可以使用pselect和ppoll這兩個函式來遮蔽訊號的影響,從而避免函式執行過程中受訊號的干擾。

前幾種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 基於...