2010-12-09 95 views
0

我有以下程序(DGRAM套接字)從時間服務器中檢索時間。該程序不會按預期打印當前時間。使用SOCK_DGRAM從服務器獲取信息時的問題

#define DAYTIME_SERVER_PORT 13 

int main(int argc, char *argv[]) 
{ 

    int connectionFd, in; 
    struct sockaddr_in servaddr; 
    char buf[BUFSIZ]; 

    connectionFd = socket(AF_INET, SOCK_DGRAM, 0); 
    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(DAYTIME_SERVER_PORT); 
    inet_pton(AF_INET,"time.mit.edu", &servaddr.sin_addr); 

    sendto(connectionFd,buf ,1, 0,(struct sockaddr_in *)&servaddr, sizeof(servaddr)); 

    in = recv(connectionFd, buf, BUFSIZ, 0) ; 
    buf[in] = 0 ; 
    printf("Time is %s \n",buf); 

    close(connectionFd); 


} 

我的問題是 - 我在哪裏犯錯?任何代碼更改和寶貴的建議表示讚賞。我不知道如何使用recvform函數,因此嘗試了recv。我正在連接的白天服務器是time.mit.edu

回答

9

inet_pton()不查找主機名稱,例如time.mit.edu。它僅用於將IP地址的字符串形式(如"18.7.21.144")轉換爲套接字地址。

您應該使用getaddrinfo()來查找名稱,如"time.mit.edu"。它也可以做查找daytime端口號的工作。你的代碼是這樣:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 

int main(int argc, char *argv[]) 
{ 
    struct addrinfo *addr; 
    struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM }; 
    int err; 
    int connectionFd, in; 
    char buf[1024]; 

    err = getaddrinfo("time.mit.edu", "daytime", &hints, &addr); 
    if (err) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err)); 
     return 1; 
    } 

    connectionFd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 

    sendto(connectionFd, "." , 1, 0, addr->ai_addr, addr->ai_addrlen); 

    freeaddrinfo(addr); 

    in = recv(connectionFd, buf, sizeof buf - 1, 0) ; 
    buf[in] = 0 ; 
    printf("Time is %s \n",buf); 

    close(connectionFd); 
    return 0; 
} 

(看,媽媽:支持IPv6的白天;)

當然,您也應該檢查socket()sendto()recv()返回值,就像我做爲getaddrinfo()。特別是,考慮是否recv()失敗並返回-1,會發生什麼......

+0

請不要教孩子們不受保護的性行爲:) – 2010-12-09 04:12:01

2

你檢查既不的socket(2)sendto(2)返回值,也不是recv(2)功能,在返回錯誤-1和設置全局變量errno(3)。習慣總是檢查系統調用返回。

您給出recv()BUFSIZ作爲可用空間,然後在收到的長度後寫入一個字節。如果BUFSIZ確實很大(大於任何UDP數據報,即大於2^16),那麼這可能不是真正的問題,但是如果您收到完整的數據,您可能會超出緩衝區。

至於你的代碼中的真正問題 - @ caf已經回答了。

0

您的代碼基本上是正確的。我不得不調整一下,因爲我正在運行Windows,但它適用於我。所以這裏有一些你可以看看的東西:

  • sendto的返回值是什麼?這可能會告訴你至少你是否連接好。

  • 檢查您的地址是否正確。將time.mit.edu的IP地址直接硬編碼到servaddr.sin_addr中可能更容易,以消除inet_pton導致問題的任何可能性。

  • BUFSIZ是什麼值?通常它被設置在stdio.h中,但是你確定它不是零嗎?

  • 您不明確地將協議設置爲IPPROTO_UDP。這通常是可以的,因爲當你設置protocol = 0時你的套接字庫會選擇一個合適的協議。使用getsockopt(SO_PROTOCOL_INFO)檢查它是否正確(或者在您調用socket()時顯式設置它)。

  • 防火牆阻礙了你的行爲嗎?試試telneting到time.mit.edu:13。它應該打印出時間,然後關閉連接。

關於recvfrom的......它是相同的,不同的是它抓住了對主機的地址recv的。這種差異在這裏不重要。

相關問題