Читаем UNIX: разработка сетевых приложений полностью

//udpcliserv/udpservselect01.c

 1 #include "unp.h"


 2 int

 3 main(int argc, char **argv)

 4 {

 5  int listenfd, connfd, udpfd, nready, maxfdp1;

 6  char mesg[MAXLINE];

 7  pid_t childpid;

 8  fd_set rset;

 9  ssize_t n;

10  socklen_t len;

11  const int on = 1;

12  struct sockaddr_in cliaddr, servaddr;

13  void sig_chld(int);


14  /* создание прослушиваемого сокета TCP */

15  listenfd = Socket(AF_INET, SOCK_STREAM, 0);


16  bzero(&servaddr, sizeof(servaddr));

17  servaddr.sin_family = AF_INET;

18  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

19  servaddr.sin_port = htons(SERV_PORT);


20  Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

21  Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));


22  Listen(listenfd, LISTENQ);


23  /* создание сокета UDP */

24  udpfd = Socket(AF_INET, SOCK_DGRAM, 0);


25  bzero(&servaddr, sizeof(servaddr));

26  servaddr.sin_family = AF_INET;

27  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

28  servaddr.sin_port = htons(SERV_PORT);


29  Bind(udpfd, (SA*)&servaddr, sizeof(servaddr));

Создание прослушиваемого сокета TCP

14-22 Создается прослушиваемый сокет TCP, который связывается с заранее известным портом сервера. Мы устанавливаем параметр сокета SO_REUSEADDR в случае, если на этом порте существуют соединения.

Создание сокета UDP

23-29 Также создается сокет UDP и связывается с тем же портом. Даже если один и тот же порт используется для сокетов TCP и UDP, нет необходимости устанавливать параметр сокета SO_REUSEADDR перед этим вызовом функции bind, поскольку порты TCP не зависят от портов UDP.

В листинге 8.15 показана вторая часть нашего сервера.

Листинг 8.15. Вторая половина эхо-сервера, обрабатывающего TCP и UDP при помощи функции select

udpcliserv/udpservselect01.c

30  Signal(SIGCHLD, sig_chld); /* требуется вызвать waitpid() */


31  FD_ZERO(&rset);

32  maxfdp1 = max(listenfd, udpfd) + 1;

33  for (;;) {

34   FD_SET(listenfd, &rset);

35   FD_SET(udpfd, &rset);

36   if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {

37    if (errno == EINTR)

38     continue; /* назад в for() */

39    else

40     err_sys("select error");

41   }

42   if (FD_ISSET(listenfd, &rset)) {

43    len = sizeof(cliaddr);

44    connfd = Accept(listenfd, (SA*)&cliaddr, &len);


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

46     Close(listenfd); /* закрывается прослушиваемый сокет */

47     str_echo(connfd); /* обработка запроса */

48     exit(0);

49    }

50    Close(connfd); /* родитель закрывает присоединенный сокет */

51   }

52   if (FD_ISSET(udpfd, &rset)) {

53    len = sizeof(cliaddr);

54    n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA*)&cliaddr, &len);


55    Sendto(udpfd, mesg, n, 0, (SA*)&cliaddr, len);

56   }

57  }

58 }

Установка обработчика сигнала SIGCHLD

30 Для сигнала SIGCHLD устанавливается обработчик, поскольку соединения TCP будут обрабатываться дочерним процессом. Этот обработчик сигнала мы показали в листинге 5.8.

Подготовка к вызову функции select

Перейти на страницу:

Все книги серии Мастер-класс

Секреты резьбы по дереву
Секреты резьбы по дереву

Изделия из древесины и материалов, имитирующих ее текстуру, привычным образом окружают нас в повседневной жизни, поэтому мы относимся к ней как к чему-то обыденному. Но как только ее коснется умелая рука мастера резьбы по дереву, рождается произведение искусства и раскрываются такие качества древесины, как богатая фактура, разнообразие цветов, особая теплота. Эта книга поможет читателю открыть для себя удивительный мир творчества и познать секреты резьбы по дереву. Автор надеется, что начинающие резчики найдут в ней интересный и полезный материал, который позволит им стать мастерами. В приложении представлены рисунки орнаментов и различных узоров, которые на первых порах можно копировать, а по мере приобретения навыка на их основе разрабатывать свои образцы.

Галина Алексеевна Серикова

Сделай сам / Хобби и ремесла / Руководства / Дом и досуг / Словари и Энциклопедии

Похожие книги