簡體   English   中英

選擇多個非阻塞連接

[英]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秒)。 那么在這種情況下我如何實現目標呢?

  1. 如果所有套接字都准備就緒,程序將繼續執行。
  2. 如果任何一個插座未准備好,程序可能會在此阻塞2秒鍾。

是的, select是在假設您要在每個套接字准備好后就對其進行服務的前提下設計的。

如果我了解您要執行的操作,那么最簡單的方法就是在准備好fdset中刪除每個套接字。 如果集合中還有剩余的套接字,請使用gettimeofday向下調整超時,然后再次調用select 當集合為空時,所有四個插槽均可用,您可以繼續進行。

共有三種基本方法:

如果您想保持嚴格的便攜性 ,則需要進行以下迭代:

  • 根據您選擇的當前時間和超時來計算結束時間
  • 周期:
  • -創建尚未准備好的fdset
  • -計算最大等待時間
  • select()
  • -記住那些已經准備好的fds
  • -如果達到結束時間或所有fds准備就緒則中斷
  • 結束循環
  • 現在,您已經了解了准備就緒的fds和經過的時間

如果您想保持可移植性,但可以使用線程

  • 開始n個線程
  • 每個線程選擇一個fd
  • 加入所有線程

如果您不需要攜帶 :大多數操作系統都具有針對這種情況的功能,例如Windows / .NET具有WaitAll(以及異步發送和事件)

我看不到您陳述的目標和陳述的問題之間的聯系。 正確地說,select()會阻塞,直到至少有一個套接字准備好為止,但是根據上面的目標2,這正是您想要的。 在您聲明的目標中,直到所有四個插槽同時准備就緒,才可以進行阻塞。

您還應該注意,除非發送緩沖區已滿,否則套接字幾乎總是可以進行寫操作,這意味着接收方的接收緩沖區已滿,這意味着接收方比發送方慢。 因此,單獨使用select()作為底層寫計時器並不是一個好主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM