11.5. Функции getservbyname и getservbyport
11.5. Функции getservbyname и getservbyport
Службы, как и узлы, также часто идентифицируются по именам. Используя в нашем коде имя службы вместо номера порта, при условии, что имена служб сопоставляются номерам портов в некотором файле (обычно /etc/services), мы получаем следующее преимущество. Если этой службе будет назначен другой номер порта, то нам будет достаточно изменить одну строку в файле /etc/services, вместо того чтобы перекомпилировать все приложения. Следующая функция, getservbyname, ищет службу по ее заданному имени.
ПРИМЕЧАНИЕ
Канонический список номеров портов, назначенных определенным службам, поддерживается IANA и располагается по адресу http://www.iana.org/assignments/port-numbers (см. раздел 2.9). Файл /etc/services чаще всего содержит некоторое подмножество списка IANA.
#include <netdb.h>
struct servent *getservbyname(const char *servname, const char *protoname);
Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки
Функция возвращает указатель на следующую структуру:
struct servent {
char *s_name; /* официальное имя службы */
char **s_aliases; /* список псевдонимов */
int s_port; /* номер порта, записанный в сетевом порядке байтов */
char *s_proto; /* протокол, который нужно использовать */
};
Имя службы servname должно быть указано обязательно. Если задан и протокол (то есть если protoname — непустой указатель), то в структуре должен быть указан совпадающий протокол. Некоторые службы Интернета позволяют использовать и TCP, и UDP (например, DNS и все службы, представленные в табл. 2.1), в то время как другие поддерживают только один протокол (протоколу FTP требуется TCP). Если аргумент protoname не задан и служба поддерживает несколько протоколов, то возвращаемый номер порта зависит от реализации. Обычно это не имеет значения, поскольку службы, поддерживающие множество протоколов, как правило, используют один и тот же номер порта для протоколов TCP и UDP, но вообще говоря это не гарантируется.
Более всего в структуре servent нас интересует поле номера порта. Поскольку номер порта возвращается в сетевом порядке байтов, мы не должны вызывать функцию htons при записи его в структуру адреса сокета.
Типичные вызовы этой функции могут быть такими:
struct servent *sptr;
sptr = getservbyname("domain", "udp"); /* DNS с использованием UDP */
sptr = getservbyname("ftp", "tcp"); /* FTP с использованием TCP */
sptr = getservbyname("ftp", NULL); /* FTP с использованием TCP */
sptr = getservbyname("ftp", "udp"); /* этот вызов приведет к ошибке */
Поскольку протоколом FTP поддерживается только TCP, второй и третий вызовы эквивалентны, а четвертый вызов приводит к ошибке. Вот соответствующие строки из файла /etc/services:
freebsd % grep -e ^ftp -e ^domain /etc/services
ftp-data 20/tcp #File Transfer [Default Data]
ftp 21/tcp #File Transfer [Control]
domain 53/tcp #Domain Name Server
domain 53/udp #Domain Name Server
ftp-agent 574/tcp #FTP Software Agent System
ftp-agent 574/udp #FTP Software Agent System
ftps-data 989/tcp # ftp protocol, data, over TLS/SSL
ftps 990/tcp # ftp protocol, control, over TLS/SSL
Следующая функция, getservbyport, ищет службу по заданному номеру порта и (не обязательно) протоколу.
#include <netdb.h>
struct servent *getservbyport(int port, const char *protname);
Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки
Значение аргумента port должно быть записано в сетевом порядке байтов. Типичные примеры вызова этой функции приведены ниже:
struct servent *sptr;
sptr = getservbyport(htons(53), "udp"); /* DNS с использованием UDP */
sptr = getservbyport(htons(21), "tcp"); /* FTP с использованием TCP */
sptr = getservbyport(htons(21), NULL); /* FTP с использованием TCP */
sptr = getservbyport(htons(21), "udp"); /* этот вызов приведет к ошибке */
Последний вызов оказывается неудачным, поскольку нет службы, использующей порт 21 с протоколом UDP.
Помните, что некоторые номера портов используются с TCP для одной службы, а с UDP — для совершенно другой, например:
freebsd % grep 514 /etc/services
shell 514/tcp cmd #like exec, but automatic
syslog 514/udp
Здесь показано, что порт 514 используется командой rsh с TCP и демоном syslog с UDP. Это характерно для портов 512-514.
Данный текст является ознакомительным фрагментом.