2011-06-09 5 views
3

J'ai écrit un programme simple qui lit l'entrée de stdin et il envoie sur TCP à un serveur écoute sur le port 15557.programme réseau fonctionne sous Linux, pas sous Cygwin

Quand je compiler et exécuter sous Linux, il fonctionne bien. Cependant, lorsque je tente de compiler et exécuter sous Cygwin, il échoue avec le message d'erreur suivant:

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

J'ai Exclue des problèmes de pare-feu/réseau, comme je suis capable de se connecter via telnet à ce même serveur et envoyer les mêmes données saisies à la main.

Une idée de ce qui ne va pas ici?

MISE À JOUR

Après @ l'indice de Hasturkun, j'ai commencé le programme sous gdb pour vérifier ce que le résultat est gethostbyname. Ici, il est, immédiatement après l'appel 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 

Je ne comprends pas comment interpréter la chaîne « > \ de 002V0 ». Est-ce censé être une adresse internet?

/UPDATE

FWIW, tout le programme est présenté ci-dessous:

#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

Est-ce votre propre message d'erreur étant imprimé, ou quelque chose d'une bibliothèque? Si c'est le vôtre (c'est-à-dire votre propre appel à 'perror' ou quelque chose de ce genre), alors avez-vous la section de code pour cela? – Jason

+0

@Jason Je crois que cela vient de l'échec de connecter l'appel à 'perror', environ 6 lignes de la fin du programme. – lindelof

+0

ne dirait-il pas "Impossible de rechercher l'adresse IP du serveur"? ... Je ne vois pas n'importe où il est dit "Impossible de construire la connexion de données". Je suppose que cette partie du message est une chaîne que vous avez passée à 'perror' quelque part. Si ce n'est pas le cas, alors je devrais voir une de vos chaînes signifiant un appel raté à 'connect', etc. – Jason

Répondre

1

Cette ligne

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

est incorrect. h_addr_list contient les adresses de struct in_addr ou struct in6_addr, la longueur est donnée en h_length et le type peut être déterminé via h_addrtype.

Pour obtenir l'adresse, memcpy ou attribuer le type approprié

+0

J'ai démarré le programme sous GDB pour vérifier ce qui se passe sur cette ligne et mis à jour la question avec les résultats.Je dois dire que je suis encore plus confus maintenant, car le programme ne fonctionnera plus sous Linux: -o – lindelof

+0

@lindelof: Ce n'est pas une chaîne, c'est une 'struct in_addr' (ce qui était faux auparavant dans ma réponse, depuis corrigé) vous pouvez l'assigner par exemple. 'sockaddr-> sin_addr = * (struct in_addr *) serverent-> h_addr_list [0];' – Hasturkun

+0

Je suis ébahi, ça marche. Mais la page 'gethostyname (3)' indique que 'gethostbyname' renvoie une structure dont le champ' h_addr_list' est un 'char **'. Comment 'h_addr_list [0]' peut-il être converti en 'struct in_addr *'? – lindelof

0

L'appel connect() échoue parce que l'adresse non valide. Il est très probable que l'appel à gethostbyname() renvoie une structure sans adresse utile (c'est-à-dire h_addr_list [0] == 0).

Pas vraiment sûr comment interagit avec Cygwin le client DNS ...

+0

Cela pourrait être. En fait, le programme échoue également sous Linux, bien que de manière imprévisible. Voir la mise à jour de la question. – lindelof

Questions connexes