2015-02-06 77 views
0

這是一個簡單的服務器,它只接受連接,然後打印套接字描述符。出於某種原因,每當我運行這個時,我收到的唯一套接字描述符的值爲0.這甚至發生在多個客戶端同時連接的情況下。我似乎誤解了accept()的行爲,或者在我的代碼中找不到一些錯誤。這裏是代碼:accept()一直返回0

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

/* Utility for consisely killing the program. */ 
void abort_program(const char *error_message) 
{ 
    fputs(error_message, stderr); 
    exit(EXIT_FAILURE); 
} 

/* Establishes a passive listening port, returns socket descriptor. */ 
int setup_passive_port(int port) 
{ 
    struct protoent *ptrp; // pointer to a protocol table entry 
    struct sockaddr_in sad; // structure to hold server's address 
    int  sd;    // socket descriptor for listening 

    /* Map TCP transport protocol name to protocol number. */ 
    if (((long int) (ptrp = getprotobyname("tcp"))) == 0) 
     abort_program("ERROR: Cannot map TCP to protocol number\n"); 

    /* Create a socket. */ 
    sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto); 
    if (sd < 0) 
     abort_program("ERROR: Socket creation failed\n"); 

    /* Prepare the socket address structure. */ 
    memset((char *) &sad, 0, sizeof(sad)); 
    sad.sin_family = AF_INET; 
    sad.sin_addr.s_addr = INADDR_ANY; 
    sad.sin_port = htons((u_short) port); 

    /* Bind a local address to the socket. */ 
    if (bind(sd, (struct sockaddr*) &sad, sizeof(sad)) < 0) 
     abort_program("ERROR: Bind failed\n"); 

    /* Establish passive listener socket. */ 
    if (listen(sd, 0) < 0) 
     abort_program("ERROR: Listen failed\n");  

    return sd; 
} 

int main(int argc, char *argv[]) 
{ 
    struct sockaddr_in cad; // structure to hold client's address 
    int  alen;   // length of address 
    int  sd;    // incoming socket 
    int  listener;  // listening socket 

    listener = setup_passive_port(30000); 

    while (1) { 

     if (sd = accept(listener, (struct sockaddr*) &cad, &alen) < 0) 
      abort_program("ERROR: Accept failed\n"); 

     printf("%d\n", sd); 

    } 

} 

你能幫我理解爲什麼嗎?感謝您的考慮。

+2

您是否試圖設置backlog參數以偵聽類似1或更高的內容? 0長度的隊列有時是有限的樂趣... – BitTickler 2015-02-06 15:35:27

+2

0是一個有效的文件discriptor接受返回,如果它沒有被使用,雖然不太可能。你是否接受多個連接?是非阻塞模式下的偵聽套接字。並且是否有監聽隊列爲0,你可以增加它 – cmidi 2015-02-06 15:40:09

+1

從技術上講,你的'socket()'調用應該指定'domain'(第一個)參數爲'AF_INET',而不是'PF_INET'。然而,在實踐中,這兩個宏似乎巧合地解決了我的環境中的相同價值。 – 2015-02-06 15:50:47

回答

4

您需要做的一件事就是在調用accept()之前將您的alen設置爲sizeof(sockaddr_in)。另一個是至少clang抱怨你的if(accept()...)行中缺失的括號。這裏是固定的版本。

telnet localhost 30000按預期工作。

同時將你的int alen改爲socklen_t alen。

int main(int argc, char *argv[]) 
{ 
    struct sockaddr_in cad; // structure to hold client's address 
    socklen_t  alen = sizeof(sockaddr_in);   // length of address 
    int  sd;    // incoming socket 
    int  listener;  // listening socket 

    listener = setup_passive_port(30000); 

    while (1) { 

     if ((sd = accept(listener, (struct sockaddr*) &cad, &alen)) < 0) 
      abort_program("ERROR: Accept failed\n"); 

     printf("%d\n", sd); 

    } 

} 
+0

啊,是的,謝謝。問題在於括號,其中'sd'被設置爲'accept(...)<0'的結果。所以我很sl。。我很欣賞你的第二套眼睛。 – Cocksure 2015-02-06 16:13:25

+0

哦。我浪費了很多時間,因爲我從未設置過'alen = sizeof(sockaddr)'。我只是把它定義爲:'socklen_t alen;'。然後,我的第一個客戶端總是會得到一些無效的ipv6地址,比如':: 0',但是隨後我從'accept()'返回的所有函數都會工作,因爲'alen'會被更新。 – spsteffl 2015-09-25 18:04:36