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));
}
4

1 に答える 1

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()。さらに、同じ関数の2つの場所ではsizeof(servaddr)なく、(ポインターのサイズである)を使用します。sizeof(*servaddr)

getaddrinfo()廃止された呼び出しではなく、最新のAPIを使用することを強くお勧めしgethostbyname()ます。

于 2013-01-23T18:38:33.563 に答える