2016-02-11 100 views
0

我只是想等我連接我的套接字後,看看我能寫入它。 因此,我創建&連接我的套接字,並使用「選擇」來完成這項工作,除非......不正確地分類。奇怪的行爲與選擇等待寫入套接字

這裏是我的代碼:

int SocketToBox(char boxIp[INET6_ADDRSTRLEN], int port) 
{ 
    struct sockaddr_in boxAddress; 
    int    sock  = -1; 

    if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) { 
     printf("%s : socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0) : errno = '%s'.\n", __func__, strerror(errno)); 
     return (-1); 
    } 

    memset(&boxAddress, 0, sizeof(boxAddress)); 
    boxAddress.sin_family = AF_INET; 
    boxAddress.sin_port = htons(port); 
    if (inet_pton(AF_INET, boxIp, &boxAddress.sin_addr) != 1) { 
     printf("%s : inet_pton(AF_INET, boxIp<'%s'>, &boxAddress.sin_addr) : errno = '%s'.\n", __func__, boxIp, strerror(errno)); 
     close(sock); 
     return (-1); 
    } 

    if (connect(sock, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) == -1) { 
     if (errno != EINPROGRESS) { 
      printf("%s : connect(sock<%d>, (struct sockaddr *)&boxAddress, sizeof(boxAddress)) : errno = '%s'.\n", __func__, sock, strerror(errno)); 
      close(sock); 
      return (-1); 
     } 
    } 
    return (sock); 
} 



int main(void) 
{ 
    int sock; 
    fd_set writeFdSet; 
    char *message = "Hello World !"; 

    if ((sock = SocketToBox("192.192.192.192", 2000)) == -1) { 
     printf("%s : SocketToBox(\"192.192.192.192\", 2000) : callstack.\n", __func__); 
     return (1); 
    } 

    FD_ZERO(&writeFdSet); 
    FD_SET(sock, &writeFdSet); 

    if (select(sock + 1, NULL, &writeFdSet, NULL, NULL) == -1) { 
     printf("%s : select(sock<%d> + 1, NULL, &writeFdSet, NULL, NULL) : errno = '%s'.", __func__, sock, strerror(errno)); 
     return (1); 
    } 

    if (FD_ISSET(sock, &writeFdSet)) { 
     printf("socket UP.\n"); 

     if (send(sock, message, strlen(message), MSG_DONTWAIT) == -1) { 
      printf("%s : send(sock<%d>, message<'%s'>, strlen(message)<%zu>, MSG_DONTWAIT) : errno '%s'.\n", __func__, sock, message, strlen(message), strerror(errno)); 
      return (1); 
     } 
     printf("Message sended.\n"); 
    } else { 
     printf("socket DOWN.\n"); 
    } 

    FD_ZERO(&writeFdSet); 
    if (sock == -1) { 
     close(sock); 
    } 
    return (0); 
} 

而且我的輸出:

socket UP. 
main : send(sock<3>, message<'Hello World !'>, strlen(message)<13>, MSG_DONTWAIT) : errno 'Connection timed out'. 

我錯過了什麼? 選擇返回1,我也不明白!爲什麼是1而不是0? 爲什麼我的套接字被標記爲「可寫」通過選擇發送失敗? 我可以確保你不能ping 192.192.192.192。

+0

我建議你從閱讀[選擇'手冊頁](http://man7.org/linux/man-pages/man2/select.2.html)開始,它應該解釋這兩種行爲。 –

+0

謝謝......真的。我已經閱讀了這個選擇手冊頁,我不明白這個行爲。 我會嘗試以這種方式來解決我的問題:爲什麼一個套接字,我故意連接到什麼都沒有,標記爲選擇可寫? –

+0

'SOCK_NONBLOCK'和'MSG_DONTWAIT'是非標準的(即非POSIX)。這是什麼操作系統? –

回答

0

the select manual page

成功時,select()pselect()返回包含在三個文件中描述符的數量返回描述符集

這就是爲什麼select功能爲您返回1:它返回在集合中設置一個描述符。


對於第二個問題,也從手動頁面:

文件描述符被認爲是準備好,如果它能夠進行對應的I/O操作(例如,read(2)而不阻塞,或足夠小的write(2))。

那些writefds將被觀看,看是否有可用空間寫(雖然大量寫仍可塊)

因此,所有select會告訴你的是,描述符內部緩衝區中有可用的空間,但它沒有說什麼有關數據是否可以實際發送。

+0

好的,謝謝。 我完全不明白,在人的第一次閱讀,但它是有道理的。 操作系統只是說,他有一個緩衝區準備寫入,而不是套接字連接。 猜我會找到另一種方式來知道一個插座是否真的連接。謝謝。 –

0

因爲寫入未連接的套接字不會阻塞 - 而這是唯一保證您的選擇。