Linux下Socket連線超時的一種實現方法

2021-06-20 12:55:32 字數 3632 閱讀 8772

目前各平台通用的設定套接字(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...