Литмир - Электронная Библиотека
Содержание  
A
A

 4 main(int argc, char **argv)

 5 {

 6  int sockfd, family, port;

 7  const int on = 1;

 8  pid_t pid;

 9  socklen_t salen;

10  struct sockaddr *sa, *wild;

11  struct ifi_info *ifi, *ifihead;

12  if (argc == 2)

13   sockfd = Udp_client(NULL, argv[1], (void**)&sa, &salen);

14  else if (argc == 3)

15   sockfd = Udp_client(argv[1], argv[2], (void**)&sa, &salen);

16  else

17   err_quit("usage; udpserv04 [ <host> ] <service or port>");

18  family = sa->sa_family;

19  port = sock_get_port(sa, salen);

20  Close(sockfd); /* хотим узнать семейство, порт salen */

21  for (ifihead = ifi = Get_ifi_info(family, 1),

22   ifi ! = NULL; ifi = ifi->ifi_next) {

23   /* связывание с многоадресными адресами */

24   sockfd = Socket(family, SOCK_DGRAM, 0);

25   Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

26   sock_set_port(ifi->ifi_addr, salen, port);

27   Bind(sockfd, ifi->ifi_addr, salen);

28   printf("bound %s\n", Sock_ntop(ifi->ifi_addr, salen));

29   if ((pid = Fork()) == 0) { /* дочерний процесс */

30    mydg_echo(sockfd, ifi->ifi_addr, salen);

31    exit(0); /* никогда не выполняется */

32   }

33   if (ifi->ifi_flags & IFF_BROADCAST) {

34    /* попытка связывания с широковещательным адресом */

35    sockfd = Socket(family, SOCK_DGRAM, 0);

36    Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

37    sock_set_port(ifi->ifi_brdaddr, salen, port);

38    if (bind(sockfd, ifi->ifi_brdaddr, salen) < 0) {

39     if (errno == EADDRINUSE) {

40      printf("EADDRINUSE: %s\n",

41       Sock_ntop(ifi->ifi_brdaddr, salen));

42      Close(sockfd);

43      continue;

44     } else

45      err_sys("bind error for %s",

46     Sock_ntop(ifi->ifi_brdaddr, salen));

47    }

48    printf ("bound %s\n", Sock_ntop(ifi->ifi_brdaddr, salen));

49    if ((pid = Fork()) == 0) { /* дочерний процесс */

50     mydg_echo(sockfd, ifi->ifi_brdaddr, salen);

51     exit(0); /* никогда не выполняется */

52    }

53   }

54  }

55  /* связывание с универсальным адресом */

56  sockfd = Socket(family, SOCK_DGRAM, 0);

57  Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

58  wild = Malloc(salen);

59  memcpy(wild, sa, salen); /* копирует семейство и порт */

60  sock_set_wild(wild, salen);

61  Bind(sockfd, wild, salen);

62  printf("bound %s\n", Sock_ntop(wild, salen));

63  if ((pid = Fork()) == 0) { /* дочерний процесс */

64   mydg_echo(sockfd, wild, salen);

65   exit(0); /* никогда не выполняется */

66  }

67  exit(0);

68 }

69 void

70 mydg_echo(int sockfd, SA *myaddr, socklen_t salen)

71 {

72  int n;

73  char mesg[MAXLINE];

74  socklen_t len;

75  struct sockaddr *cli;

76  cli = Malloc(salen);

77  for (;;) {

78   len = salen;

79   n = Recvfrom(sockfd, mesg, MAXLINE, 0, cli, &len);

80   printf("child %d, datagram from %s",

81    getpid(), Sock_ntop(cli, len));

82   printf(", to %s\n", Sock_ntop(myaddr, salen));

83   Sendto(sockfd, mesg, n, 0, cli, len),

84  }

85 }

Глава 24

24.1. Да, разница есть. В первом примере два байта отсылаются с единственным срочным указателем, который указывает на байт, следующий за

b
. Во втором же примере (вызываются две функции) сначала отсылается символ
a
с указателем срочности, который указывает на следующий за ним байт, а за этим сегментом следует еще один TCP-сегмент, содержащий символ
b
с другим указателем срочности, указывающим на следующий за ним байт.

395
{"b":"225366","o":1}