2011-06-09 65 views
3

我寫了一個簡單的程序,從stdin讀取輸入,並將其發送通過TCP服務器偵聽端口15557.網絡程序運行在Linux下,沒有Cygwin的

當我編譯和Linux下它運行工作正常。然而,當我嘗試編譯和Cygwin下運行它,它失敗,出現以下錯誤信息:

$ ./a.out servername.net 15557 < test.dat 
Unable to connect: Cannot assign requested address 

我已經排除了任何防火牆/網絡問題,因爲我能夠通過telnet連接到相同的服務器併發送手動輸入的相同數據。

任何想法這裏怎麼了?

UPDATE

繼@ Hasturkun的線索,我已經開始GDB下的程序來檢查一下結果gethostbyname是。這是,在gethostbyname調用後立即:

(gdb) print *serverent 
$2 = {h_name = 0x603217 "bilbo.neurobat.net", h_aliases = 0x603030, h_addrtype = 2, h_length = 4, h_addr_list = 0x6031c0} 
(gdb) print serverent->h_addr_list[0] 
$3 = 0x60322c ">\002V0" 
(gdb) print atoi(">\002V0") 
$5 = 0 

我不知道如何解釋「> \ 002V0」字符串。這應該是一個互聯網地址?

/UPDATE

FWIW,整個程序如下:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <string.h> 
#include <unistd.h> 

#include "neurocli.h" 

int main(int argc, char* argv[]) { 
    char *line = NULL; 
    char buf[40] = {0}; 
    ssize_t write_len = 0, read_len; 
    size_t n = 0; 
    int neuro_socket; 

    if (argc != 3) { 
    fprintf(stderr, "Usage: %s host port\n", argv[0]); 
    return -1; 
    } 

    neuro_socket = open_tcp_socket(argv[1], atoi(argv[2])); 

    /* Main loop: connect, write, read, re-connect and finally close */ 
    while ((write_len=getline(&line, &n, stdin)) != -1) { 
    printf("# %s", line); 
    if (write(neuro_socket, line, write_len) < 0) { 
     perror("Unable to write to server"); 
     exit(EXIT_FAILURE); 
    } 
    if (*line=='\n') { 
     read_len = read(neuro_socket, buf, 40); 
     buf[read_len] = '\0'; 
     printf("%s", buf); 
     close(neuro_socket); 
     neuro_socket = open_tcp_socket(argv[1], atoi(argv[2])); 
    } 
    free(line); 
    line = NULL; /* getline() needs this */ 
    } 
    free(line); 
    close(neuro_socket); 
    return 0; 
} 


int open_tcp_socket(char *server, int port) { 
    int result; 
    static struct sockaddr_in *sockaddr; 

    /* Create socket */ 
    if ((result = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
    perror("Unable to create socket"); 
    exit(EXIT_FAILURE); 
    } 

    if (sockaddr==NULL) 
    sockaddr = make_sockaddr(server, port); /* never mind the memory leak */ 

    /* Connect */ 
    if (connect(result, (struct sockaddr*)sockaddr, sizeof(*sockaddr)) != 0) { 
    perror("Unable to connect"); 
    exit(EXIT_FAILURE); 
    } 

    return result; 
} 

struct sockaddr_in *make_sockaddr(char *name, int port) { 
    struct sockaddr_in *sockaddr = malloc(sizeof(struct sockaddr_in)); 
    struct hostent *serverent; 

    memset(sockaddr, 0, sizeof(*sockaddr)); 
    sockaddr->sin_family = AF_INET; 
    sockaddr->sin_port = htons(port); 

    if ((serverent = gethostbyname(name)) == NULL) { 
    perror("Unable to lookup server IP address"); 
    exit(EXIT_FAILURE); 
    } 

    sockaddr->sin_addr.s_addr = atoi(serverent->h_addr_list[0]); 

    return sockaddr; 
} 
+0

是正被打印出來自己的錯誤消息,或者說從庫?如果它是你自己的(也就是你自己對'perror'或者那種性質的調用),那麼你有代碼段嗎? – Jason 2011-06-09 12:49:30

+0

@Jason我相信這是因爲未能將調用連接到'perror',從程序結束後大概有6行。 – lindelof 2011-06-09 12:58:58

+0

不會說「無法查找服務器IP地址」? ...我只是沒有看到它說「無法建立數據連接」的地方。我假設消息的一部分是你在某處傳遞給'perror'的字符串。如果不是,那麼我應該看到你的一串字符串表示一個連接失敗的調用,等等。 – Jason 2011-06-09 13:32:19

回答

1

此行

sockaddr->sin_addr.s_addr = atoi(serverent->h_addr_list[0]); 

不正確。 h_addr_list包含地址struct in_addrstruct in6_addr,長度在h_length中給出,類型可以通過h_addrtype確定。

要獲取地址,memcpy或將其分配給適當類型

+0

我已經啓動了GDB下的程序來檢查該行發生了什麼,並用結果更新了問題。我必須說現在我更加困惑,因爲該程序在Linux下不能工作:-o – lindelof 2011-06-10 13:55:06

+0

@lindelof:它不是一個字符串,它是一個'struct in_addr'(以前在我的答案中是錯誤的,自更正以來),您可以指定它。 'sockaddr-> sin_addr = *(struct in_addr *)serverent-> h_addr_list [0];' – Hasturkun 2011-06-10 23:36:44

+0

我大吃一驚,它的工作原理。但'gethostyname(3)'頁面說''gethostbyname'返回一個struct,其'h_addr_list'字段是一個'char **'。那麼如何將'h_addr_list [0]'轉換爲'struct in_addr *'? – lindelof 2011-06-11 05:21:59

0

的connect()調用失敗,因爲在無效地址。對gethostbyname()的調用很可能返回一個沒有有用地址的結構(即h_addr_list [0] == 0)。

不能確定如何與DNS客戶端交互的cygwin ...

+0

這可能是。實際上,該程序也在Linux下失敗,儘管以不可預測的方式。查看問題的更新。 – lindelof 2011-06-10 13:55:55

相關問題