課題1:
tcpv6cはIPv4とIPv6の両方に対応しているにもかかわらず,tcpc(IPv4のみに対応)よりコードが短い.
この理由は何故か説明せよ.
(ヒント:両プログラムのアドレスとポート番号の変換処理部分に着目せよ)
tcpv.cはサーバーのアドレスのチェックとポート番号のチェックを別の行程で行っているが,
tcpv6c.cでは一つの関数を用いることで両方の処理を行っている.
tcpc.c(一部)
/* サーバのIPアドレスを調べる */
if ((dst_ip = inet_addr(argv[DST_IP])) == INADDR_NONE) {
struct hostent *he; /* ホスト情報 */
if ((he = gethostbyname(argv[DST_IP])) == NULL) {
fprintf(stderr, "gethostbyname error\n");
exit(EXIT_FAILURE);
}
memcpy((char *)&dst_ip, (char *)he->h_addr, he->h_length);
}
/* サーバのポート番号を調べる */
if (argc == 3) {
if ((port = atoi(argv[DST_PORT])) == 0) {
struct servent *se; /* サービス情報 */
if ((se = getservbyname(argv[DST_PORT], "tcp")) != NULL)
port = (int)ntohs((u_short)se->s_port);
else {
fprintf(stderr, "getservbyname error\n");
exit(EXIT_FAILURE);
}
}
} else
port = DEFAULT_PORT;
tcpc.cで使用している関数
- inet_addr()関数:インターネットホストのアドレスを「数値とドット」記法からバイナリ値へ変換して返す.
- gethostbyname()関数:与えられたホスト名に対応する構造体を返す.
- atoi()関数:nptrによって指示される文字列のはじめの部分をint型に変換する.
- getservbyname()関数:
- プロトコルを用いるサービスの名前にマッチする行を/etc/servicesから探し、その行の内容を含めたservent構造体を返す.
tcpcv6.c(一部)
memset(&info, 0, sizeof(info));
info.ai_flags = AI_CANONNAME;
info.ai_family = AF_UNSPEC;
info.ai_socktype = SOCK_STREAM;
if (getaddrinfo(argv[DST_IP], (argc == 3)?argv[DST_PORT]:DEFAULT_PORT, &info,
&res) != 0) {
perror("getaddrinfo");
exit(EXIT_FAILURE);
}
tcpcv6.cで使用している関数
- getaddrinfo()関数:
- getipnodebyname(),Getipnodebyaddr(),getservbyname(),Getservbyport()の4つの関数の機能をまとめて1つのインターフェースにした関数.よってこれのみでホストのアドレスと,ポート番号を同時に調べることができる.