0

私は C でソケット プログラミングを行っていますが、問題があります - きっと - それは私の混乱から来ています: getaddrinfo()を使用してサーバーを設定するにはどうすればよいですか? クライアントからそのアドレスを取得するにはどうすればよいですか? 私はUDPを使用しています。

(私はBeejのチュートリアルから来ましたが、まだ理解していません)

これは私のサーバーのコードです ( mhgc.netとポート 3051 で実行しようとしていますが、... ホスト名を設定する方法が見つかりませんか? 申し訳ありませんが、混乱しています):

int sockd;

/* Get my IP address */
struct addrinfo hints, * servinfo;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;  // use my own address
if( getaddrinfo(NULL, "3051", &hints, &servinfo) != 0 ) {
    /* Yes, below is not... 'pretty code'; this is just an attempt */
    errorf("Failed to get server address: %s", gai_strerror( getaddrinfo(NULL, "3051", &hints, &servinfo) ));
    exit(EXIT_FAILURE);
    return 1;
}

struct addrinfo * p = NULL;
for(p = servinfo; p != NULL; p = p->ai_next) {
    if( (sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1 ) {
        perror("Cannot open socket");
        continue;
    }

    if(bind(sockd, p->ai_addr, p->ai_addrlen) == -1) {
        close(sockd);
        perror("Cannot bind to port");
        continue;
    }

    break;
}

if(p == NULL) {
    error("listener: failed to bind socket");
    exit(EXIT_FAILURE);
    return 0;
}

freeaddrinfo(servinfo);

struct sockaddr_storage clientinfo;
socklen_t clientinfo_len = sizeof(clientinfo);

char buffer[15];
memset(buffer, 0, sizeof(buffer));
if( recvfrom(sockd, buffer, sizeof(buffer), 0, (struct sockaddr *)&clientinfo, &clientinfo_len) == -1 ) {
    perror("Error receiving packet");
    exit(EXIT_FAILURE);
    return 0;
}

char s[INET6_ADDRSTRLEN];
printf("listener: got packet from %s\n", inet_ntop(clientinfo.ss_family, get_in_addr((struct sockaddr *)&clientinfo), s, sizeof(s)));
printf("listener: packet contains \"%s\"\n", buffer);

/* Close the socket descriptor */
close(sockd);

    /* And now, exit, or whatever I need ... ... ... */

そして私のクライアントのために:

int sockd;

struct addrinfo hints, * servinfo;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
//hints.ai_flags = AI_CANONNAME;
if( getaddrinfo(MKS_HOSTNAME, "www", &hints, &servinfo) != 0 ) {
    errorf("Failed to get server address: %s", gai_strerror( getaddrinfo(NULL, "3051", &hints, &servinfo) ));
    return 1;
}

struct addrinfo * p = NULL;
for(p = servinfo; p != NULL; p = p->ai_next) {
    if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
        perror("Cannot open socket");
        continue;
    }

    break;
}

if(p == NULL) {
    error("talker: failed to bind socket");
    return 2;
}

if( sendto(sockd, "this-is-a-test", strlen("this-is-a-test")+1, 0, p->ai_addr, p->ai_addrlen) == -1 ) {
    perror("Error sending packet");
    return 1;
}

freeaddrinfo(servinfo);

close(sockd);

errorerrorfは、アプリケーションのデバッグに役立つマクロです。それらについて心配する必要はありません。

別のヒントとして、Beej のチュートリアルにある talker.c は、ホスト名を使用してサーバーを「検索」します。listener.c と talker.c をダウンロードしてコンパイル (make listener && make talker) しましたが、talker 引数として何を渡せばよいかわかりませんでした。リスナーのホスト名は? どうすれば見つけられますか?またすみません。私はそれについて本当に混乱しています:S

gcc コンパイラ v4.4.5 を使用して、Debian GNU/Linux "squeeze" に取り組んでいます

4

1 に答える 1

0

サーバー上で、特定のアドレスをリッスンしたくない場合は、単にアドレスを渡しanyます (すべてのアドレス要素をゼロに設定します)。ローカル アドレスを取得するために を呼び出してgetaddrinfoも、適切な回答は得られません。サービスの名前ではなく、ホストの IP アドレスを知りたいので、serviceパラメーターを に設定します。NULL

クライアントをサーバーに接続するには、サーバーの IP アドレス (サーバー上で実行/sbin/ifconfigし、クライアントが到達可能なアドレスを検索する) またはホスト名 (つまりhostname、サーバー上で実行し、クライアント上でその名前を使用する) を使用します。サーバーへの接続用)。

于 2012-07-13T22:49:29.087 に答える