[英]select for multiple non-blocking connections
我有一個單線程程序。 它每五秒鍾將消息發送到四個目的地。 我不希望connect()
被阻止。 所以我正在寫這樣的程序:
int j, rc, non_blocking=1, sockets[4], max_fd=0;
struct sockaddr server=get_server_addr();
fd_set fdset;
const struct timeval conn_timeout = { 2, 0 }; /* 2 seconds */
for (j=0; j<4; ++j)
{
sockets[j]=socket( AF_INET, SOCK_STREAM, 0 );
ioctl(sockets[j], FIONBIO, (char *)&non_blocking);
connect(sockets[j], &server, sizeof (server));
}
/* prepare fd_set */
FD_ZERO ( &fdset );
for (j=0;j<4;++j)
{
if (sockets[j] != -1 )
{
FD_SET ( sockets[j], &fdset );
if ( sockets[j] > max_fd )
{
max_fd = sockets[j];
}
}
}
rc=select(max_fd + 1, NULL, &fdset, NULL, &conn_timeout );
if(rc > 0)
{
for (j=0;j<4;++j)
{
if(sockets[j]!=-1 && FD_ISSET(sockets[j],&fdset))
{
/* send() */
}
}
}
/* close all valid sockets */
但是,似乎select()
在一個文件描述符准備好后立即返回,而不是阻塞conn_timeout
(2秒)。 那么在這種情況下我如何實現目標呢?
是的, select
是在假設您要在每個套接字准備好后就對其進行服務的前提下設計的。
如果我了解您要執行的操作,那么最簡單的方法就是在准備好fdset中刪除每個套接字。 如果集合中還有剩余的套接字,請使用gettimeofday
向下調整超時,然后再次調用select
。 當集合為空時,所有四個插槽均可用,您可以繼續進行。
共有三種基本方法:
如果您想保持嚴格的便攜性 ,則需要進行以下迭代:
select()
如果您想保持可移植性,但可以使用線程 :
如果您不需要攜帶 :大多數操作系統都具有針對這種情況的功能,例如Windows / .NET具有WaitAll(以及異步發送和事件)
我看不到您陳述的目標和陳述的問題之間的聯系。 正確地說,select()會阻塞,直到至少有一個套接字准備好為止,但是根據上面的目標2,這正是您想要的。 在您聲明的目標中,直到所有四個插槽同時准備就緒,才可以進行阻塞。
您還應該注意,除非發送緩沖區已滿,否則套接字幾乎總是可以進行寫操作,這意味着接收方的接收緩沖區已滿,這意味着接收方比發送方慢。 因此,單獨使用select()作為底層寫計時器並不是一個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.