Добавить в цитаты Настройки чтения

Страница 132 из 399

//names/daytimetcpcli.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int sockfd, n;

 6  char recvline[MAXLINE + 1];

 7  socklen_t len;

 8  struct sockaddr_storage *ss;

 9  if (argc != 3)

10   err_quit

11    ("usage, daytimetcpcli <hostname/IPaddress> <service/port#>");

12  sockfd = Tcp_co

13  len = sizeof(ss);

14  Getpeername(sockfd, (SA*)&ss, &len);

15  printf("co

16  while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {

17   recvline[n] = 0; /* завершающий нуль */

18   Fputs(recvline, stdout);

19  }

20  exit(0);

21 }

9-11 Теперь нам требуется второй аргумент командной строки для задания либо имени службы, либо номера порта, что позволит нашей программе соединяться с другими портами.

12 Теперь весь код сокета для этого клиента выполняется функцией tcp_co

13-15 Мы вызываем функцию getpeername, чтобы получить адрес протокола сервера и вывести его. Мы делаем это для проверки протокола, используемого в примерах, которые скоро покажем.

Обратите внимание, что функция tcp_co

Эта версия нашего клиента работает и с IPv4, и с IPv6, тогда как версия, представленная в листинге 1.1, работала только с IPv4, а версия из листинга 1.2 — только с IPv6. Сравните нашу новую версию с представленной в листинге Д.6, которую мы написали, чтобы использовать функции gethostbyname и getservbyname для поддержки и IPv4, и IPv6.

Сначала мы задаем имя узла, поддерживающего только IPv4:

freebsd % <b>daytimetcpcli linux daytime</b>

co

Sun Jul 27 23:06:24 2003

Затем мы задаем имя узла, поддерживающего и IPv4, и IPv6:

freebsd % <b>daytimetcpcli aix daytime</b>

co

Sun Jul 27 23:17:13 2003

Используется адрес IPv6, поскольку у узла имеется и запись типа AAAA, и запись типа А. Кроме того, функция tcp_co

В следующем примере мы указываем на необходимость использования именно адреса IPv4, задавая имя узла с суффиксом -4, что, как мы отмечали в разделе 11.2, в соответствии с принятым нами соглашением означает имя узла, который поддерживает только записи типа А:

freebsd % <b>daytimetcpcli aix-4 daytime</b>

co

Sun Jul 27 23:17:48 2003

11.13. Функция tcp_listen

Наша следующая функция, tcp_listen, выполняет обычные шаги сервера TCP: создание сокета TCP, связывание его с заранее известным портом с помощью функции bind и разрешение приема входящих запросов через соединение. В листинге 11.6 представлен исходный код.

#include &quot;unp.h&quot;

int tcp_listen(const char *<i>hostname</i>, const char *<i>service</i>, socklen_t *<i>lenptr</i>);

<i>В случае успешного выполнения возвращает дескриптор присоединенного сокета, в случае ошибки не возвращает ничего</i>

Листинг 11.6. Функция tcp_listen: выполнение обычных шагов сервера TCP

//lib/tcp_listen.c

 1 #include &quot;unp.h&quot;

 2 int

 3 tcp_listen(const char *host, const char *serv, socklen_t *addrlenp)

 4 {

 5  int listenfd, n;

 6  const int on = 1;

 7  struct addrinfo hints, *res, *ressave;

 8  bzero(&amp;hints, sizeof(struct addrinfo));

 9  hints.ai_flags = AI_PASSIVE;

10  hints.ai_family = AF_UNSPEC;

11  hints.ai_socktype = SOCK_STREAM;

12  if ((n = getaddrinfo(host, serv, &amp;hints, &amp;res)) != 0)

13   err_quit(&quot;tcp_listen error for %s, %s: %s&quot;,

14    host, serv, gai_strerror(n));