Операционная система UNIX - Робачевский Андрей Михайлович
Шрифт:
Интервал:
Закладка:
/* Номер порта, который обслуживается сервером */
#define PORTNUM 1500
main (argc, argv)
char *argv[];
int argc;
{
int s;
int pid;
int i, j;
struct sockaddr_in serv_addr;
struct hostent *hp;
char buf[80]="Hello, World!";
/* В качестве аргумента клиенту передается доменное имя
хоста, на котором запущен сервер. Произведем трансляцию
доменного имени в адрес */
if ((hp = gethostbyname(argv[1])) == 0) {
perror("Ошибка вызова gethostbyname()");
exit(3);
}
bzero(&serv_addr, sizeof(serv_addr));
bcopy(hp->h_addr, &serv_addr.sin_addr, hp->h_length);
serv_addr.sin_family = hp->h_addrtype;
serv_addr.sin_port = htons(PORTNUM);
/* Создадим сокет */
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Ошибка вызова socket!)");
exit(1);
}
fprintf(stderr, "Адрес клиента: %sn",
inet_ntoa(serv_addr.sin_addr));
/* Создадим виртуальный канал */
if (connect (s, (struct sockaddr*)&serv_addr,
sizeof(serv_addr)) == -1) {
perror("Ошибка вызова connect()");
exit(1);
}
/* Отправим серверу сообщение и получим его обратно */
send(s, buf, sizeof(buf), 0);
if (recv(s, buf, sizeof(buf) , 0) < 0) {
perror("Ошибка вызова recv()");
exit(1);
}
/* Выведем полученное сообщение на экран */
printf("Получено от сервера: %sn", buf);
close(s);
printf("Клиент завершил работу nn");
}
Программный интерфейс TLI
При обсуждении реализации сетевой поддержки в BSD UNIX был рассмотрен программный интерфейс доступа к сетевым ресурсам, основанный на сокетах. В данном разделе описан интерфейс транспортного уровня (Transport Layer Interface, TLI), который обеспечивает взаимодействие прикладных программ с транспортными протоколами.
TLI был впервые представлен в UNIX System V Release 3.0 в 1986 году. Этот программный интерфейс тесно связан с сетевой подсистемой UNIX, основанной на архитектуре STREAMS, изолируя от прикладной программы особенности сетевой архитектуры. Вместо того чтобы непосредственно пользоваться общими функциями STREAMS, рассмотренными в предыдущей главе, TLI позволяет использовать специальный набор вызовов, специально предназначенных для сетевых приложений. Для преобразования вызовов TLI в функции интерфейса STREAMS используется библиотека TLI, которая в большинстве систем UNIX имеет название libnsl.a или libnsl.so.
Схема использования функций TLI во многом сходна с рассмотренным интерфейсом сокетов и зависит от типа используемого протокола — с предварительным установлением соединения (например, TCP) или без него (например, UDP).
На рис. 6.18 и 6.19 представлены схемы использования функций TLI для транспортных протоколов с предварительным установлением соединения и без установления соединения. Можно отметить, что эти схемы очень похожи на те, с которыми мы уже встречались в разделе "Межпроцессное взаимодействие в BSD UNIX. Сокеты" главы 3 при обсуждении сокетов. Некоторые различия отмечены ниже при описании функций TLI.
Рис. 6.18. Схема вызова функций TLI для протокола с предварительным установлением соединения
Рис. 6.19. Схема вызова функций TLI для протокола без предварительного установления соединения
Прежде чем перейти к обсуждению функций TLI, остановимся на определении адреса коммуникационного узла. TLI не накладывает никаких ограничений на формат адреса, возлагая интерпретацию на протоколы нижнего уровня. Благодаря этому, один и тот же интерфейс может быть использован при работе с различными семействами сетевых протоколов.
Для определения адреса TLI предоставляет общую структуру данных netbuf, имеющую вид:
struct netbuf {
unsigned int maxlen;
unsigned int len;
char *buf;
}
Поле buf указывает на буфер, в котором может передаваться адрес узла, maxlen определяет его размер, a len — количество данных в буфере, т.е. размер адреса. Эта структура по своему назначению похожа на структуру sockaddr, которая является общим определением адреса коммуникационного узла для сокетов. Далее рассматривается пример сетевого приложения, основанного на TLI, где показано, как netbuf используется при передаче адреса для протоколов TCP/IP.
Структура netbuf используется в TLI для хранения не только адреса, но и другой информации — опций протокола и прикладных данных. Эта структура является составной частью более сложных структур данных, используемых при передаче параметров в функциях TLI. Для упрощения динамического размещения этих структур библиотека TLI предоставляет две функции: t_alloc(3N) для размещения структуры и t_free(3N) для освобождения памяти. Эти функции имеют следующий вид:
#include <tiuser.h>