next up previous
Next: IPv4,IPv6対応 server0.c Up: プログラムソース Previous: プログラムソース

IPv4,IPv6対応 client0.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>

int main __P((int, char **));

int
main(argc, argv)
     int argc;
     char **argv;
{
  //struct hostent *hp;  ******IPv6では使用できない********
  struct addrinfo hints, *hp; /*** hostent のかわり****/
  struct servent *sp;
  unsigned long lport;
  u_int16_t port;
  char *ep;

  //  struct sockaddr_in6 dst;  *****不要*****

  int dstlen;
  size_t l;
  int s;

  //  char hbuf[INET6_ADDRSTRLEN]; ***inet_ntop()を使わないのでこれも******

  char buf[1024];
  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

  /* 引数の数をチェック */
  if (argc != 3) {
    fprintf(stderr, "usage: test host port\n");
    exit(1);
    /*NOTREACHED*/
  }

  /* アドレスをバイナリに変換 */
  //  hp = gethostbyname(argv[1]);  *****使用できない*****

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;  /*IPv4, IPv6 どちらであるかを明示しない.*/
  hints.ai_socktype = SOCK_STREAM;
  getaddrinfo(argv[1], argv[2], &hints, &hp);
  if (!hp) {
    fprintf(stderr, "%s: %s\n", argv[1], hstrerror(h_errno));
    exit(1);
    /*NOTREACHED*/
  }
  
  //if (hp->ai_addrlen != sizeof(dst.sin6_addr)) {
  //  fprintf(stderr, "%s: unexpected address length\n", argv[1]);
  //  exit(1);
  //  /*NOTREACHED*/
  // }

  /* ポート番号をバイナリに変換 */
  sp = getservbyname(argv[2], "TCP");
  if (sp) {
    port = sp->s_port & 0xffff;
  } else {
    ep = NULL;
    errno = 0;
    lport = strtoul(argv[2], &ep, 10);
    if (!*argv[2] || errno || !ep || *ep) {
      fprintf(stderr, "%s: no such service\n", argv[2]);
      exit(1);
      /*NOTREACHED*/
    }
    if (lport & ~0xffff) {
      fprintf(stderr, "%s: out of range\n", argv[2]);
      exit(1);
      /*NOTREACHED*/
    }

    port = htons(lport & 0xffff);
  }
  endservent();

  /* 最初に帰ってきたアドレスに接続する */
  //memset(&dst, 0, sizeof(dst));
  //dst.sin_family = AF_INET;

  /* linux/Solarisでは以下の行は不要 */
  //dst.sin_len = sizeof(struct sockaddr_in);
  //memcpy(&dst.sin6_addr, hp->ai_addrlen, sizeof(dst.sin6_addr));
  //dst.sin6_port = port;
  //dstlen = sizeof(struct sockaddr_in6);
  
  s = socket(hp->ai_family, hp->ai_socktype, hp->ai_protocol);
  if (s < 0) {
    perror("socket");
    exit(1);
    /*NOTREACHED*/
  }

  /******検証用********************/
  //  if(hp->ai_family == AF_INET6) {
  //  printf("6");
  //inet_ntop(hp->ai_family, &(((struct sockaddr_in6 *)hp->ai_addr)->sin6_addr), hbuf, sizeof(hbuf));
  //}
  //else{
  //  printf("4");
  //  inet_ntop(hp->ai_family, hp->ai_addr, ibuf, sizeof(ibuf));
  //}
  /*****検証用-ed******************/

  getnameinfo(hp->ai_addr, hp->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);

  fprintf(stderr, "trying %s port %u\n", hbuf, ntohs(port));

  if (connect(s, hp->ai_addr, hp->ai_addrlen) < 0) {
    perror("connect");
    exit(1);
    /*NOTREACHED*/
  }

  while ((l = read(s, buf, sizeof(buf))) > 0)
    write(STDOUT_FILENO, buf, l);
  close(s);
  exit(0);
  /*NOTREACHED*/
}



fumiya nakamura 2006-02-10