2011-06-09 63 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

相关问题