慶應義塾大学
2007年度 秋学期

ネットワーク・プログラミング(C言語)
Network Programming in C

2007年度秋学期 火曜日2時限
科目コード: 13070 / 2単位
カテゴリ:
開講場所:SFC
授業形態:講義
担当: Rodney Van Meter
E-mail: rdv@sfc.keio.ac.jp

第6回 11月13日
Lecture 6, November 13: Naming: DNS requests

Outline of This Lecture

Near the bottom of these notes are a couple of corrections to the existing programs.

DNS: The Doman Name Service

Basic Operation

The standard analogy is that the DNS system is the phone book for the Internet: it translates human-readable names (or domain names) to numeric addresses, or IP addresses, both IPv4 (known as A records) and IPv4 (known as AAAA records, pronounced "quad A records").

Domain name space, from Wikipedia Theoretical DNS recursion (from Wikipedia)
Reverse lookups are of the form 194.141.178.203.in-addr.arpa

Implications, Politics and History

DECsystem-20 (from research.microsoft.com)

Naming APIs

We use the function getaddrinfo() to map an ASCII name to a sockaddr structure usable by our programs. getnameinfo() performs the reverse lookup. Both of these can cause actual DNS requests on the wire.

The library functions inet_ntop() and inet_pton() transform human-readable IP addresses into their binary form, and vice-versa.

Variants

A Better Makefile

On BSD systems, you will need to use gmake instead of make to use this Makefile.

CFLAGS=-g

TARGETSOURCES=client-rdv.c server-wiki-rdv.c server-udp-rdv.c \
	client-udp-rdv.c client-udp-wiki.c

LIBRARIES=mylib.a

LIBSOURCES=mylib.c
TESTSOURCES=mylibtest.c gai.c
HEADERFILES=prototypes.h

LIBOBJS=$(subst .c,.o,$(LIBSOURCES))

ALLSOURCES=$(LIBSOURCES) $(TESTSOURCES) $(TARGETSOURCES)

TESTBINARIES=$(subst .c,,$(TESTSOURCES))
TARGETBINARIES=$(subst .c,,$(TARGETSOURCES))
ALLBINARIES=$(TARGETBINARIES) $(TESTBINARIES)


all:			$(ALLBINARIES)

server-wiki-rdv:	server-wiki-rdv.c $(LIBRARIES)
	$(CC) $(CFLAGS) -o server-wiki-rdv server-wiki-rdv.c $(LIBRARIES)

client-rdv:		client-rdv.c $(LIBRARIES)
	$(CC) $(CFLAGS) -o client-rdv client-rdv.c $(LIBRARIES)

server-udp-rdv:		server-udp-rdv.c $(LIBRARIES)
	$(CC) $(CFLAGS) -o server-udp-rdv server-udp-rdv.c $(LIBRARIES)

client-udp-wiki:	client-udp-wiki.c $(LIBRARIES)
	$(CC) $(CFLAGS) -o client-udp-wiki client-udp-wiki.c $(LIBRARIES)

gai:	gai.c $(LIBRARIES)
	$(CC) $(CFLAGS) -o gai gai.c $(LIBRARIES)

mylib.a: $(LIBOBJS)
	ar r mylib.a $(LIBOBJS)

clean:
	rm -f *.o *.a *.d $(ALLBINARIES) TAGS

# automatically generated dependency files
include $(subst .c,.d,$(ALLSOURCES))

# rules for generating dependency files
%.d: %.c
	$(CC) -M $(CFLAGS) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

Correction to TCP Client Program

In the TCP client program, there were errors in the get_stream function that prevented it from compiling on BSD. Below is the correct function:

int get_stream(char *host, char *service){
  int error, fd;
  struct addrinfo *ai, *ai2, hints;
  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];  memset((void *)&hints, 0, sizeof(struct addrinfo));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_family |= PF_UNSPEC;
  // hints.ai_flags |= AI_NUMERICSERV;

  if (error = getaddrinfo(host, service, &hints, &ai)) {
    fprintf(stderr, "getaddrinfo(%s, %s, ...): %s (%d)\n", host, service, gai_strerror(error),
            error);
    exit(-1);
  }
  for (ai2 = ai; ai; ai = ai->ai_next) {
    if (error = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
                            sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
      fprintf(stderr, "getnameinfo(%p, %d, %p, %d, %p, %d, %d): %s(%d)\n",
              ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
              NI_NUMERICHOST | NI_NUMERICSERV, gai_strerror(error), error);
      continue;
    }
    fprintf(stdout, "Trying %s port %s...\n", hbuf, sbuf);
    if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
      fprintf(stderr, "socket(%d, %d, %d): ", ai->ai_family,
              ai->ai_socktype, ai->ai_protocol);
      perror("get_stream");
      continue;
    }
    if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
      fprintf(stderr, "connect(%d, %p, %d): \n", fd, ai->ai_addr,
              ai->ai_addrlen);
      perror("get_stream");
      close(fd);
      continue;
    }
    freeaddrinfo(ai2);
    return fd;
  }
  freeaddrinfo(ai2);
  fprintf(stderr, "No connections result.\n");
  return -1;
}

宿題
Homework

This week's homework (submit via email):

  1. Test your TCP and UDP clients against my server.
  2. Capture the packet trace.
  3. Create the file mylib.c, if you don't have it, and add the functions report_mysocket() and report_partner() to it, and use them in your TCP and UDP servers.
  4. Create prototypes for those functions and create a matching header file.
  5. Use a more thorough Makefile, with dependencies made automatically. You will need to use GNU make (possibly called gmake) to use this file.

Next Lecture

第7回 11月13日
Lecture 7, November 13: Binary data encodings

Additional Information

その他