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

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

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

第3回 10月23日 Lecture 4, October 23:
Basic socket programming 1

Outline of This Lecture

What's a Socket? aka Internet Protocol addressing (v4/v6)

Last week, we talked about identifiers for Internet connections. The data structure and programming paradigm we use for those connections is known as a socket, and the identifier that makes a unique socket is:

Once a connection is established, sending and receiving data on both the client and server is similar. However, getting the socket started is a little different on the client than on the server.

For Internet services using TCP or UDP, your service name is your port number. Important services use well-known port numbers, assigned by the IANA.

Socket Operation

Let's look at how a server uses sockets. Using a stream, or connection-oriented protocol such as TCP is easier. The following steps must be done:

Server Example Code

// Server code in C
// adapted from http://en.wikipedia.org/wiki/Berkeley_sockets
 
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>

int main()
{
  struct addrinfo hint;
  struct sockaddr_storage bindaddr_storage;
  struct sockaddr_in6 *bindaddr6 = 
    (struct sockaddr_in6 *)&bindaddr_storage;
  struct sockaddr_in *bindaddr = 
    (struct sockaddr_in *)&bindaddr_storage;
  struct addrinfo *result;
  struct sockaddr_storage peer;
  int peersize;
  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
  int retval;

  int i32SocketFD = socket(PF_INET6, SOCK_STREAM, 0);
 
  char msg[] = "Success!\n";

  if(-1 == i32SocketFD)
    {
      perror("can not create socket");
      exit(-1);
    }
  
  bzero(&bindaddr_storage, sizeof(bindaddr_storage));
  bindaddr6->sin6_family = AF_INET6;
  bindaddr6->sin6_addr = in6addr_any;	/* struct assignment */
  bindaddr6->sin6_port = htons(12345);
 
  if(-1 == bind(i32SocketFD,(struct sockaddr*) bindaddr6,
                sizeof(struct addrinfo)))
    {
      printf("error bind failed");
      perror("main");
      exit(-1);
    }
 
  if(-1 == listen(i32SocketFD, 10))
    {
      printf("error listen failed");
      exit(-1);
    }

  // Here, you should print out your local address using
  // getsockname() and getnameinfo() (and gai_strerror on error)

  for(; ;)
    {
      int i32ConnectFD = accept(i32SocketFD, NULL, NULL);
 
      if(0 > i32ConnectFD)
	{
          // improve error reporting here, using perror()
	  printf("error accept failed");
	  exit(-1);
	}


      // Here, you should print out your local address 
      // and the peer address using
      // getsockname(), getpeername(), and getnameinfo()
      // (and gai_strerror on error)

      // perform read write operations ...
      // add error checking and reporting here
      write(i32ConnectFD, msg, sizeof(msg));
      // wait one minute; this lets us see the connection in place, and
      // even see the behavior as we try to start a second connection
      // at the same time
      sleep(60);

      // add error checking and reporting here
      shutdown(i32ConnectFD, 2);
 
      // add error checking and reporting here
      close(i32ConnectFD);
    }
  // add error checking and reporting here
  close(i32SocketFD);
  return 0;
}

Your operation, after some of the modifications in the homework, should look something like this:

Server and telnet screen shot

Tools

Many tools for monitoring network traffic and debugging the packets that go by are available.

宿題
Homework

This week's homework (submit via email):

  1. Take the above program, and edit where the comments are to print out information about the connections, using getnameinfo(), getpeerinfo(), and gai_strerror().
  2. Test for errors from the system calls in the above code. Use perror() where appropriate.
  3. Modify the above server so that it calls fork() and creates a second process after accepting the connection. The parent should close() the connection socket and return to waiting for a new connection, while the child should close the initial socket, process the connection, then exit.
  4. Learn to use a wire monitoring tool, such as Wireshark or tcpdump. Capture the packets of two connections to your server to show that both connections are being processed at the same time.

Next Lecture

第4回 10月30日
Lecture 4, October 30: Basic socket programming 2

Additional Information

その他