Linux/Unix网络编程指南(Socket 编程)—(12)
作者:转载自:更新时间:2009-8-2

数据报 Sockets
我不想讲更多了,所以我给出代码 talker.c 和 listener.c。
listener 在机器上等待在端口 4590 来的数据包。talker 发送数据包到一定的 机器,他包含用户在命令行输入的东西。
这里就是 listener.c:
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <string.h>
  #include <sys/types.h>
  #include <netinet/in.h>
  #include <sys/socket.h>
  #include <sys/wait.h>
  #define MYPORT 4950  /* the port users will be sending to */
  #define MAXBUFLEN 100
  main()
  {
    int sockfd;
    struct sockaddr_in my_addr;  /* my address information */
    struct sockaddr_in their_addr; /* connector's address information */
   int addr_len, numbytes;
   char buf[MAXBUFLEN];
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
      perror("socket");
     exit(1);
   }
    my_addr.sin_family = AF_INET;     /* host byte order */
    my_addr.sin_port = htons(MYPORT);   /* short, network byte order */
    my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
    bzero(&(my_addr.sin_zero), 8);    /* zero the rest of the struct */
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
                                   == -1) {
      perror("bind");
      exit(1);
   }
    addr_len = sizeof(struct sockaddr);
    if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN, 0, \
             (struct sockaddr *)&their_addr, &addr_len)) == -1) {
      perror("recvfrom");
     exit(1);
    }
    printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
    printf("packet is %d bytes long\n",numbytes);
    buf[numbytes] = '\0';
    printf("packet contains \"%s\"\n",buf);
    close(sockfd);
  }
注意在我们的调用 socket(),我们最后使用了 SOCK_DGRAM。同时,没有 必要去使用 listen() 或者 accept()。我们在使用无连接的数据报套接口!
下面是 talker.c:
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <string.h>
  #include <sys/types.h>
  #include <netinet/in.h>
 #include <netdb.h>
  #include <sys/socket.h>
  #include <sys/wait.h>
  #define MYPORT 4950  /* the port users will be sending to */
  int main(int argc, char *argv[])
  {
    int sockfd;
    struct sockaddr_in their_addr; /* connector's address information */
    struct hostent *he;
    int numbytes;
    if (argc != 3) {
      fprintf(stderr,"usage: talker hostname message\n");
      exit(1);
    }
    if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */
      herror("gethostbyname");
      exit(1);
    }
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
     perror("socket");
      exit(1);
    }
   their_addr.sin_family = AF_INET;   /* host byte order */
    their_addr.sin_port = htons(MYPORT); /* short, network byte order */
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);   /* zero the rest of the struct */
   if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0, \
      (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
      perror("sendto");
     exit(1);
    }
    printf("sent %d bytes to %s\n",numbytes,inet_ntoa(their_addr.sin_addr));
    close(sockfd);
    return 0;
  }
这就是所有的了。在一台机器上运行 listener,然后在另外一台机器上运行 talker。观察他们的通讯!
Except for one more tiny detail that I've mentioned many times in the past: connected datagram sockets. I need to talk about this here, since we're in the datagram section of the document. Let's say that talker calls connect() and specifies the listener's address. From that point on, talker may only sent to and receive from the address specified by connect(). For this reason, you don't have to use sendto() and recvfrom(); you can simply use send() and recv().