Выбрать главу

#include <netdb.h>

struct servent * getservbyname(const char * name,

 const char * protocol);

Первый параметр name представляет собой имя службы, о которой в приложении требуется информация. Параметр protocol указывает протокол для использования. База данных служб содержит информацию о других протоколах (особенно UDP); конкретное определение протокола позволяет функции игнорировать информацию по другим протоколам. Параметр protocol обычно является строкой "tcp", хотя могут использоваться и другие имена протоколов, например, "udp".

Функция getservbyname() возвращает указатель на структуру, которая содержит информацию о запрашиваемой службе. Информация может перезаписываться при последующем вызове getservbyname(), поэтому важные данные нужно сохранять в приложении. Функция getservbyname() возвращает следующую информацию:

#include <netdb.h>

struct servent {

 char * s_name;     /* имя службы */

 char ** s_aliases; /* псевдонимы службы */

 int s_port;        /* номер порта */

 char * s_proto;    /* протокол для использования */

}

Каждая служба может иметь несколько имен, ассоциированных с ней, но только один номер порта. Переменная s_name регистрирует каноническое имя службы, s_port содержит официальный номер порта данной службы (представленный в сетевом порядке байтов), s_proto представляет протокол для использования (например, "tcp"). Член s_aliases является массивом указателей псевдонимов службы (указатель NULL обозначает конец списка).

Если функция не выполняет свою работу, то она возвращает NULL и устанавливает h_errno. Ниже приведен пример программы, которая извлекает TCP-службу, указанную в командной строке, и выводит на экран каноническое имя, номер порта и все псевдонимы данной службы.

 1: /* services.с */

 2:

 3: #include <netdb.h>

 4: #include <netinet/in.h>

 5: #include <stdio.h>

 6:

 7: /* Отображает номер порта TCP и все псевдонимы службы,

 8:    указанной в командной строке */

 9:

10: /* services.с отыскивает номер порта для службы */

11: int main(int argc, const char ** argv) {

12:  struct servent * service;

13:  char ** ptr;

14:

15:  if (argc != 2) {

16:   fprintf(stderr, "поддерживается только одиночный аргумент\n");

17:   return 1;

18:  }

19:

20:  /* поиск службы в /etc/services, в случае неудачи

21:     передается ошибка */

22:  service = getservbyname(argv[1] , "tcp");

23:  if (!service) {

24:   herror("getservbyname failed");

25:   return 1;

26:  }

27:

28:  printf("служба: %s\n", service->s_name);

29:  printf("tcp-порт: %d\n", ntohs(service->s_port));

31:  /* отобразить все псевдонимы, которые имеет данная служба */

32:  if (*service->s_aliases) {

33:   printf("псевдонимы:");

34:   for (ptr = service->s_aliases; *ptr; ptr++)

35:    printf(" %s", *ptr);

36:   printf("\n");

37:  }

38:

39:  return 0;

40: }

Ниже показан пример запуска программы. Обратите внимание на то, что она извлекает службы либо по каноническому имени, либо по псевдониму.

$ ./services http

служба: http

tcp-порт: 80

$ ./services source

служба: chargen

tcp-порт: 19

псевдонимы: ttytst source

Глава 18

Время

18.1. Вывод времени и даты

18.1.1. Представление времени

В системах Unix и Linux время отслеживается в секундах до или после начала эпохи, которое определяется как полночь 1 января 1970 года по UTC[148]. Положительные значения времени относятся к периоду после начала эпохи; отрицательные — до начала эпохи. Для того чтобы обеспечить работу процессов в режиме текущего времени, в Linux, как и во всех остальных версиях Unix, предусмотрен системный вызов time().

#include <time.h>

time_t time (time_t *t);

Функция time() возвращает количество секунд, прошедших с момента начала эпохи. Если значение t не является нулевым, то данная функция передает в эту переменную количество секунд, прошедших с начала эпохи.

Для решения некоторых проблем требуется более высокая разрешающая способность. В Linux предусмотрен еще один системный вызов — gettimeofday(), который предоставляет более подробную информацию.

#include <sys/time.h>

#include <unistd.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

struct timeval {

 int tv_sec;  /* секунды */

 int tv_usec; /* микросекунды */

};

struct timezone {

 int tz_minuteswest; /* минуты на запад от Гринвича */

 int tz_dsttime;     /* тип корректировки dst */

};

На большинстве платформ, включая i386, система Linux поддерживает возможность очень точного измерения времени. Стандартные персональные компьютеры содержат встроенные часы, которые обеспечивают информацию о текущем времени с точностью до микросекунд. Оборудование Alpha и SPARC также предлагает высокоточный таймер. На некоторых других платформах система Linux может отслеживать время только в пределах разрешающей способности системного таймера, который в общем случае устанавливается на значение 100 Гц. В связи с этим член tv_usec структуры timeval в подобных системах может иметь меньшую точность.

В sys/time.h определены пять макросов для обработки структур timeval.

timerclear(struct timeval *)

Данный макрос очищает структуру timeval.

timerisset(struct timeval *)

Данный макрос проверяет структуру timeval на заполнение (другими словами, отличен ли хотя бы один элемент от нуля).

вернуться

148

UTC — Universal Coordinated Time (универсальное синхронизированное время), на которое иногда ошибочно ссылаются как на UCT, приблизительно эквивалентное среднему времени по Гринвичу (GMT) и зулу. Описание всех часовых поясов выходит за рамки материала, рассматриваемого в настоящей книге.