我們知道。對於乙個套接字的讀寫(read/write)操作預設是堵塞的。假設當前套接字還不可讀/寫,那麼這個操作會一直堵塞下去,這樣對於乙個須要高效能的server來說,是不能接受的。所以,我們能夠在進行讀寫操作的時候能夠指定超時值,這樣就讀寫操作就不至於一直堵塞下去。
在涉及套接字的i/o操作上設定超時的方法有三種:
1:呼叫alarm,它在指定的超時期滿時產生sigalrm訊號。這種方法涉及訊號處理,而訊號處理在不同的實現上存在差異,並且可能干擾程序中現有的alarm呼叫。
2:在select中堵塞等待i/o(select有內建的時間限制),依次取代直接堵塞在read或write呼叫上。(linux2.6以後的核心也能夠使用epoll的epoll_wait)。
3:使用較新的so_rcvtimeo和so_sndtimeo套接字選項。這種方法的問題在於並不是全部的實現都支援這兩個套接字選項。
上述這三個技術都適用於輸入和輸出操作(read、write。及其變體recv/send, readv/writev, recvfrom, sendto)。
只是我們也期待能夠用於connect的技術,由於tcp內建的connect超時相當長(典型值為75秒),而我們在寫server程式的時候,也不會希望乙個連線的建立須要花費這麼長時間。
select可用來在connect上設定超時的先決條件是對應的套接字是非堵塞的。而那兩個套接字選項對connect並不適用。同一時候也應當指出,前兩個技術適用於不論什麼描寫敘述符。而第三個技術只適用於套接字描寫敘述符。
>>>>使用select對connect設定超時:
#include #include #include #include #include #include #include #include #include #include #include #include #define port 9900
#define maxdatasize 5000
int main(int argc, char **ar**)
if((he = gethostbyname(ar**[1])) == null)
if((sockfd = socket(af_inet, sock_stream, 0)) == -1)
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_port = htons(port);
servaddr.sin_addr = *((struct in_addr *)he->h_addr);
fcntl(sockfd, f_setfl, o_nonblock);
timeval timeout = ;
if(connect(sockfd, (sa*)&servaddr, sizeof(struct sockaddr)) == -1)
}fd_set readset;
fd_zero(&readset);
fd_zero(&writeset);
fd_set(sockfd, &writeset);
int ret = select(sockfd+1, &readset, &writeset, null, &timeout);
printf("%d", ret);
}
>>>>使用sigalrm為connect設定超時:
#include static void connect_alarm(int);
intconnect_timeo(int sockfd, const sa* saptr, socklen_t salen, int nsec)
alarm(0); /* turn off the alarm */
signal(sigalrm, sigfunc); /* restore previous signal handler */
return (n);
}static void
connect_alarm(int signo)
>>>>使用sigalrm為recvfrom設定超時:
#include static void sig_alarm(int);
void
dig_cli(file* fp, int sockfd, const sa* pservaddr, socklen_t servlen)
else
}}static void
sig_alarm(int signo)
>>>>使用select為recvfrom設定超時:
#include int
readable_timeo(int fd, int sec)
所以上面dig_cli函式結合readable_timeo函式設定超時的程式就可變為:(堵塞在select上)
#include void
dig_cli(file* fp, int sockfd, const sa* pservaddr, socklen_t servlen)
else
}}
>>>>使用so_rcvtimeo套接字選項為recvfrom設定超時:
#include void
dig_cli(file* fp, int sockfd, const sa* pservaddr, socklen_t servlen)
else
err_sys("recvfrom error");
}recvline[n] = 0; /* null terminate */
fputs(recvline, stdout);
}}
UNIX網路程式設計 基礎套接字程式設計
就像 unix網路程式設計 裡面說的,我們可以將tcp的連線看成乙個 系統,那麼我們的套接字位址結構,就是我們的 裡面號碼,和其他能確定我們身份資訊的集合。其中ipv4的,我們已經很熟悉,還有另外的,在ipv6如果系統支援長度字段,那麼sin6 len常值必須定義,在使用這一結構時我們必須分清到底,...
UNIX網路程式設計 套接字程式設計介紹
列印當前機器是小頭派還是大頭派型別 注意,如果沒有加這兩個標頭檔案 include include 編譯時候會報 警告 隱式宣告與內建函式 printf 不相容 這個錯誤 編譯 gcc o byteorder byteorder.c include include int main int argc...
UNIX網路程式設計 原始套接字SOCK RAW
實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需要執行更底...