2013-01-23 82 views
1

這是我的問題:我正在寫一個簡單的客戶端,它將連接到服務器使用服務器的主機名和端口號作爲命令行參數。它編譯得很好,但是當我運行客戶端時,我從perror()收到一條消息,說「錯誤:地址族不受協議支持」。不知道爲什麼我得到這個錯誤,但我知道當我調用connect()時發生錯誤。出於某種原因,connect無法在我的sockaddr_in結構中找到地址族信息。任何幫助將非常感激。「協議不支持地址」當運行客戶端

int main(int argc, char* argv[]) 
{ 
    if(argv[1] == NULL) 
    { 
     printf("if 1\n"); 
     perror("Error: argv[1]:hostname\n"); 
     exit(1); 
    } 

    struct sockaddr_in* servaddr = getServerInfo(argv[1], argv[2]); 
    int socketfd = createSocket(); 

    if(socketfd < 0) 
    { 
     printf("if 2\n"); 
     perror("Error: socketfd\n"); 
     exit(1); 
    } 

    int commResult = communicate(socketfd, servaddr); 

    if(commResult < 0) 
    { 
     printf("if 3\n"); 
     perror("Error: communication\n"); 
     exit(1); 
    } 

    return 0; 
} 

struct sockaddr_in* getServerInfo(char* hostname, char* port) 
{ 
    struct sockaddr_in* servaddr = malloc((size_t)sizeof(struct sockaddr_in)); 
    struct hostent *hostptr; 
    hostptr = gethostbyname(hostname); 

    memset((void *) servaddr, 0, (size_t)sizeof(*servaddr)); 
    servaddr->sin_family = (short)(AF_INET); 
    memcpy((void*)& servaddr->sin_addr, (void *) hostptr->h_addr, hostptr->h_length); 
    servaddr->sin_port = htons((u_short)atoi(port)); 

    return servaddr; 
} 


int createSocket() 
{ 
    int socketfd = socket(AF_INET, SOCK_STREAM, 0); 
    if(socketfd < 0) 
    { 
     return -1; 
    } 

    return socketfd; 
} 

int communicate(int socketfd, struct sockaddr_in* servaddr) 
{ 
    char buffer[BUFFERSIZE]; 

    // connect to the server at the location displayed by TCPserver.c 
    if(connect(socketfd, (struct sockaddr*)&servaddr, sizeof(*servaddr)) < 0) 
    { 
     printf("if 4\n"); 
     perror("ERROR: connecting to socket\n"); 
     return -1; 
    } 

    printf("Connected to server\n"); 

    strcpy(buffer, "This is the message I want the client to echo on the screen to prove that we can communicate together.\n"); 

    write(socketfd, buffer, strlen(buffer)+1); 

    return 0; 
} 

這裏是服務器端的代碼,以及:

int main() 
{ 
char * hostname = malloc(MAXSIZE * sizeof(char)); 
char buffer[BUFFERSIZE]; 

struct sockaddr_in* servaddr = getServerInfo(hostname); 
int listensockfd = createSocket(servaddr), connsockfd; 
printServerInfo(hostname, servaddr); 

listen(listensockfd, MAX_NUM_LISTENER_ALLOWED); 

connsockfd = accept(listensockfd, NULL, NULL); 
read(connsockfd, buffer, BUFFERSIZE); 
printf("Message: %s\n", buffer); 

// free memory 
free(servaddr); 
free(hostname); 

return 0; 
} // End main 

struct sockaddr_in* getServerInfo(char* hostname) 
{ 
    struct sockaddr_in* servaddr = malloc((size_t)sizeof(struct sockaddr_in)); 
    gethostname(hostname, 32); 
    struct hostent *hostptr; 
    hostptr = gethostbyname(hostname); 

     memset((void *) servaddr, 0, (size_t)sizeof(*servaddr)); 
     servaddr->sin_family = (short)(AF_INET); 
     memcpy((void *)& servaddr->sin_addr, (void *) hostptr->h_addr, hostptr->h_length); 
     servaddr->sin_port = htons((u_short)38000); 

    return servaddr; 
} 

int createSocket(struct sockaddr_in* servaddr) 
{ 
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0); 

    bind(listensockfd, (struct sockaddr *) &servaddr, (socklen_t)sizeof(servaddr)); 

    socklen_t listensocklen = sizeof(servaddr); 
    getsockname(listensockfd, (struct sockaddr*)&servaddr, &listensocklen); 

    return listensockfd; 
} 

void printServerInfo(char* hostname, struct sockaddr_in* servaddr) 
{ 
    struct hostent *hostptr; 
    hostptr = gethostbyname(hostname); 

    printf("Host Name: %s\n", hostname); 
    printf("Host IP: %s\n", inet_ntoa(*(struct in_addr*)*hostptr->h_addr_list)); 
    printf("Port Number: %d\n", htons(servaddr->sin_port)); 
} 

回答

3

您在servaddr面前,這已經是一個指針有虛假&。實際上,您將指針在堆棧上的地址傳遞給connect(),而不是實際指向struct sockaddr_in的指針。

替換此:

if(connect(socketfd, (struct sockaddr*)&servaddr, sizeof(*servaddr)) < 0) 

與此:

if(connect(socketfd, (struct sockaddr*)servaddr, sizeof(*servaddr)) < 0) 

,它會工作。

在服務器中,bind()getsockname()createSocket()的調用中存在相同的錯誤。此外,在同一個函數的兩個地方使用sizeof(servaddr)(這是指針的大小)而不是sizeof(*servaddr)

請注意,我強烈建議使用現代的getaddrinfo() API,而不要使用過時的gethostbyname()調用。

+0

感謝Daniel Roethlisberger的幫助。我不敢相信這是一個簡單的錯誤。然而,我有一個新的錯誤。新錯誤顯示「連接被拒絕」。我環顧了這個網站上的其他帖子,他們說,通常防火牆拒絕連接或端口關閉。許多人建議我在該主機名和端口號上運行telnet。當我這樣做時說,連接被拒絕了。然而,我認爲這個錯誤與我沒有正確實現服務器或客戶端有關。所以我發佈了服務器代碼。 – user1995624

+0

我不認爲這是可能的另一個原因是因爲我在屬於同一網絡的主機上運行客戶端和服務器。也就是說,我的地方大學的網絡。 – user1995624

+1

您在'createSocket()'中調用'bind()'和'getsockname()'時犯了完全相同的錯誤。您可以通過檢查您的服務器是否使用'netstat'綁定到正確的地址/端口來檢測到問題。 –

相關問題