目前各平台通用的設定套接字(socket)連線超時的辦法是:
建立套接字,將其設定成非阻塞狀態。
呼叫connect連線對端主機,如果失敗,判斷當時的errno是否為einprogress,也就是說是不是連線正在進行中,如果是,轉到步驟3,如果不是,返回錯誤。
用select在指定的超時時間內監聽套接字的寫就緒事件,如果select有監聽到,證明連線成功,否則連線失敗。
以下是linux環境下的示例**:
#include
#include
#include
#include
#include
#include
socket
.h>
#include
#include
<
errno
.h>
#include
<
time
.h>
int main(
int argc,
char
*argv)
;socklen_t len =
sizeof
(timeo)
;fd_set set
;fd =
socket
(af_inet
,sock_stream
, 0);if
(argc =
= 4)
timeo.tv_sec =
atoi
(argv[3]);
fcntl(fd, f_setfl, fcntl(fd, f_getfl)
| o_nonblock)
;addr.sin_family =
af_inet
;addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port =
htons
(atoi
(argv[2]))
;printf
("%d\n"
,time
(null))
;if(connect
(fd,
(struct
sockaddr*)
&addr,
sizeof
(addr))=
= 0)if(
errno
!= einprogress)
fd_zero(
&set);
fd_set(fd,
&set);
retval =
select
(fd + 1,
null,&
set,
null
,&timeo);if
(retval =
=-1)
else
if(retval =
= 0)
printf
("connected\n");
return 0;
}
實際執行結果如下:
xiaosuo@gentux perl $ ./a.out 10.16.101.1 90
1180289276
timeout
1180289279
xiaosuo@gentux perl $ ./a.out 10.16.101.1 90 1
1180289281
timeout
1180289282
可以看到,以上**工作的很好,並且如果你想知道連線發生錯誤時的確切資訊的話,你可以用getsocketopt獲得:
int
error
;socklen_t errorlen =
sizeof
(error);
getsockopt
(fd, sol_socket, so_error,
&error
,&errorlen)
;
但是多少有些複雜,如果有象so_sndtimo/so_rcvtimo一樣的套接字引數可以讓超時操作跳過select的話,世界將變得更美好。當然你還可以選用象
apr一樣提供了簡單介面的庫,但我這裡要提的是另一種方法。
呵呵,引子似乎太長了點兒。讀linux核心原始碼的時候偶然發現其connect的超時引數竟然和用so_sndtimo操作的引數一致:
file: net/ipv4/af_inet.c
559 timeo = sock_sndtimeo(sk, flags & o_nonblock);
560561 if ((1 << sk->sk_state) & (tcpf_syn_sent | tcpf_syn_recv))
這意味著:
在linux平台下,可以通過在connect之前設定so_sndtimo來達到控制連線超時的目的。簡單的寫了份測試**:
#include
#include
#include
#include
socket
.h>
#include
#include
<
errno
.h>
int main(
int argc,
char
*argv)
;socklen_t len =
sizeof
(timeo)
;fd =
socket
(af_inet
,sock_stream
, 0);if
(argc =
= 4)
timeo.tv_sec =
atoi
(argv[3]);
setsockopt
(fd, sol_socket, so_sndtimeo,
&timeo, len)
;addr.sin_family =
af_inet
;addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port =
htons
(atoi
(argv[2]))
;if(connect
(fd,
(struct
sockaddr*)
&addr,
sizeof
(addr))=
=-1)
perror
("connect");
return 0;
}printf
("connected\n");
return 0;
}
執行結果:
xiaosuo@gentux perl $ ./a.out 10.16.101.1 90
1180290583
timeout
1180290586
xiaosuo@gentux perl $ ./a.out 10.16.101.1 90 2
1180290590
timeout
1180290592
和設想完全一致!
linux下socket程式設計
一 什麼是socket socket可以看成是使用者程序與核心網路協議棧的程式設計介面。socket不僅可以用於本機的程序間通訊,還可以用於網路上不同主機的程序間通訊。socket api是一層抽象的網路程式設計介面,適用於各種底層網路協議,如ipv4 ipv6。struct sockaddr in...
linux下socket程式設計
作為乙個嵌入式開發者,在實際的研發專案中,常常需要編寫socket網路程式設計介面,提供給軟體開發人員。下面將提供乙個常用的 模板 客戶端的功能可以用微控制器多功能除錯助手進行驗證 include include include include include include include def...
linux下socket程式設計
簡單的linux下socket程式設計,分別基於tcp和udp協議實現的簡單程式 linux下socket程式設計可以概括為以下幾個函式的運用 流程 將套接字繫結到伺服器的網路位址上 if bind server sockfd,struct sockaddr my addr,sizeof struc...