在套接字上設定超時的方法有以下三種:
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 ...