Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

16 if (inet_aton(argv[1], &inetaddr) == 0) {

17 err_quit("hostname error for %s: %s", argv[1],

18 hstrerror(h_errno));

19 } else {

20 inetaddrp[0] = &inetaddr;

21 inetaddrp[1] = NULL;

22 pptr = inetaddrp;

23 }

24 } else {

25 pptr = (struct in_addr**)hp->h_addr_list;

26 }

27 if ((sp = getservbyname(argv[2], "tcp")) == NULL)

28 err_quit("getservbyname error for %s", argv[2]);

29 for (; *pptr != NULL; pptr++) {

30 sockfd = Socket(AF_INET, SOCK_STREAM, 0);

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

32 servaddr.sin_family = AF_INET;

33 servaddr.sin_port = sp->s_port;

34 memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));

35 printf("trying %s\n", Sock_ntop((SA*)&servaddr, sizeof(servaddr)));

36 if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) == 0)

37 break; /* успешное завершение */

38 err_ret("connect error");

39 close(sockfd);

40 }

41 if (*pptr == NULL)

42 err_quit("unable to connect");

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

44 recvline[n] = 0; /* null terminate */

45 Fputs(recvline, stdout);

46 }

47 exit(0);

48 }

Вызов функций gethostbyname и getservbyname

13-28
Первый аргумент командной строки — это имя узла, передаваемое в качестве аргумента функции
gethostbyname
, а второй — имя службы, передаваемое в качестве аргумента функции
getservbyname
. Наш код подразумевает использование протокола TCP, что мы указываем во втором аргументе функции
getservbyname
. Если функции
gethostbyname
не удается найти нужное имя, мы вызываем функцию
inet_aton
(см. раздел 3.6), чтобы проверить, не является ли аргумент командной строки IP-адресом в формате ASCII. В этом случае формируется список из одного элемента — этого IP-адреса.

Перебор всех адресов

29-35
Теперь мы пишем вызовы функций
socket
и
connect
в цикле, который выполняется для каждого адреса сервера, пока попытка вызова функции
connect
не окажется успешной или пока не закончится список серверов. После вызова функции
socket
мы заполняем структуру адреса сокета Интернета IP-адресом и номером порта сервера. Хотя в целях увеличения производительности мы могли бы вынести из цикла вызов функции
bzero
и последующие два присваивания, наш код легче читать в таком виде, как он представлен сейчас. Установление соединения с сервером редко является основным источником проблем с производительностью сетевого клиента.

Вызов функции connect

36-39
Вызывается функция
connect
, и если вызов оказывается успешным, функция
break
завершает цикл. Если установить соединение не удается, мы выводим сообщение об ошибке и закрываем сокет. Вспомните, что дескриптор, для которого вызов функции
connect
оказался неудачным, не может больше использоваться и должен быть закрыт.

Завершение программы

41-42
Если цикл завершается, потому что ни один вызов функции
connect
не закончился успехом, программа завершает работу.

Чтение ответа сервера

43-47
Мы считываем ответ сервера и завершаем программу, когда сервер закрывает соединение.

Если мы запустим эту программу, указав один из наших узлов, на котором работает сервер времени и даты, мы получим ожидаемый результат:

freebsd % daytimetcpcli1 aix daytime

trying 192.168.42.2:13

Sun Jul 27 22:44:19 2003

Но еще интереснее запустить программу, обратившись к маршрутизатору с несколькими сетевыми интерфейсами, на котором не работает сервер времени и даты:

  • Читать дальше
  • 1
  • ...
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: