網路程式設計第十四章 套接字超時

2021-10-05 02:36:16 字數 4625 閱讀 5542

在套接字上設定超時的方法有以下三種:

1 呼叫alarm,產生sigalarm訊號,

2 在select阻塞等待io

3 使用so_rcvtimeo和so_rndtimeo選項。這個方法的問題在於並非所有實現都支援這個兩個選項。

alarm:

#include

"unp.h"

static

void

connect_alarm

(int);

intconnect_timeo

(int sockfd,

const sa *saptr,socklen_t salen ,

int nsec)

}alarm(0

);signal

(sigalrm,sigfunc)

;return n;

}static

void

connect_alarm

(int signo)

//這個訊號處理函式只是簡單的return了一下

//在多執行緒程式中正確使用訊號異常困難,建議在未執行緒化或者單執行緒中使用這個技術。

使用sigalrm為recvfrom設定超時
#include

"unp.h"

static

void

sig_alrm

(int);

void

dg_cli

(file*fp,

int sockfd,

const sa *pservaddr,socklen_t servlen)

else}}

static

void

sig_alrm

(int signo)

使用select為recvfrom設定超時
#include

"unp.h"

intreadable_timeo

(int fd,

int sec)

//本函式不支援讀操作,只是等待描述符變為可讀。

等待描述符變為可寫的函式:

#include

"unp.h"

void

dg_cli

(file*fp,

int sockfd,

const sa*pservaddr,socklen_t servlen)

else

}}

使用套接字選項so_ercvtimo為recvfrom設定超時

一旦設定超時,該套接字選項講應用於該套接字所有的讀操作. 不能為connect設定超時.

#include

"unp.h"

void

dg_cli

(fiel*fp,

const sa*pservaddr,socklen_t servlen)

else

err_sys

("recvfrom error");

} recvline[n]=0

;fputs

(recvline,

stdout);

}}

recv和send函式:
#include

"unp.h"

ssize_t recv

(int sockfd,

void

*buff,size_t nbytes,

int flags)

;ssize_t send

(int sockfd,

const

void

*buff,size_t nbytes,

int flags)

;

可以通過設定flags值來確定:目的主機是否在本地網路上,阻塞io.傳送帶外資料,檢視已經讀取的資料,返回讀操作.

readv和writev函式:

這兩個函式允許分散讀和集中寫,因為來自讀操作的輸入資料被分散到多個應用程式緩衝區中,而來自多個應用緩衝區的輸出資料則被集中提供給單個寫操作.

#include

ssize_t readv

(int filedes,

const

struct iovec *iov,

int iovcnt)

;ssize_t writev

(int filedes,

const

struct iovec*iov,

int iovcnt);其中

struct iovec

這兩個函式可以用於任何描述符,而不是僅限於套接字,writev是乙個原子操作.

recvmsg和sendmsg函式

這是最通用的io函式,

#include

ssize_t recvmsg

(int sockfd,

struct msghdr *msg,

int flags)

ssize_t sendmsg

(int sockfd,

struct msghdr *msg,

int flags)

大部分引數在msgdr結構

struct msghdr
只有recvmsg使用msgf_lags,flags值被複製到核心驅動接受處理過程,核心還更新msg_flags的值

sendmsg忽略msg_flags成員,直接只用值引數flags;

輔助資料

輔助資料由sendmsg和recvmsg的msghdr的兩個成員傳送和接受.

輔助資料有乙個或者多個輔助資料物件構成

struct cmsghdr
排隊的資料量:詳見313

套接字和標準io.

除了unix io 方法之外,還可以使用標準io函式庫,標準io函式庫可用於套接字,

1 通過呼叫fdopen,可以從任意乙個描述符建立乙個標準io流,呼叫fileno可以獲取乙個標準io流的描述符

2 標準io流也可以是全雙工的,只要以r+型別開啟,但是必須輸出之後fflush,fseek,fsetpos,才能接著呼叫乙個輸入函式.類似的,呼叫乙個輸入之後必須插入乙個fseek,fsetpos才能呼叫乙個輸出,除非遇到乙個eof;但fseek和fsetpos應用到套接字上會出錯.

3 解決2的最好方法是給乙個給定描述符開啟兩個標準io.讀和寫

#include

"unp.h"

void

str_echo

(int sockfd)

}

p315緩衝問題需要細讀.

高階輪詢技術:

其他為套接字操作設計時間限制的其他方法,但是並不是所有實現都支援.

/dev/poll介面提供了可擴充套件的輪詢大量描述符的方法,輪詢程序預先設定好查詢描述符的列表,然後進入乙個迴圈等待事件發生,每次迴圈回來不再次設定該列表.

開啟/dev/poll,初始化乙個結構,write向/dev/poll裝置上寫這個結構陣列把它傳遞給核心,然後用ioct1阻塞自身等待事件發生.

傳遞給ioct1的結構:

struct dvpoll
例子:

#include

"unp.h"

#include

void

str_cli

(file *fp,

int sockfd)

write

(fileno

(stdout

), buf, n);}

else

writen

(sockfd, buf, n);}

}}}

kqueue藉口

本介面允許程序向核心註冊描述所關注的kqueue事件的事件過濾器.

#include

#include

#include

intkqueue

(void);

//返回乙個kqueue描述符,用於後續kevent呼叫中

intkevent

(int kq,

const

struct kevent*changlist,

int nchangs;

//對所關注事件做出的更改

struct kevent *evnelist,

int nevents;

//條件所觸發的事件陣列作為函式返回值返回,

const

struct timespec *timeout;

//超時設定.

);

#include

"unp.h"

void

str_cli

(file *fp,

int sockfd)

write

(fileno

(stdout

), buf, n);}

if(kev[i]

.ident ==

fileno

(fp))}

}}}

第十四章 unix域套接字

unix域套接字實際上不是乙個實際的協議,他只是在同一臺主機上客戶和伺服器之間通訊時,使用與在不同主機上客戶和伺服器間通訊時相同的api unix域套接字分為兩種 位元組流套接字和資料報套接字 unix域套接字的好處 1 在同一臺主機上進行通訊時,是不同主機間通訊的兩倍 2 unix域套介面可以在同...

第十四章約束

約束 constraint 是一種保證資料完整性的規則。約束設定在單個字段或者多個字段組合上,寫入這些欄位的行資料必須要符合約束的規則 約束的五種型別 not null 非空約束,指定某列的所有行資料不能包含空值 unique 唯一性約束,指定列或者列的組合的所有行資料必須唯一 primary ke...

第十四章 約束

第十四章 約束 練習1 1.學校有乙個選課系統,其中包括如下關係模式 系 系編號 主鍵,系名稱 唯一鍵,系主任 非空約束,系所在校去 取值範圍只能在南湖校區和渾南校區 create table xi xi no varchar2 10 primary key,xi name varchar2 10 ...