Читать книгу 📗 "Операционная система UNIX - Робачевский Андрей Михайлович"
req.addr.maxlen = sizeof(serv_addr); req.addr.len = sizeof(serv_addr); req.addr.buf = (char*)&serv_addr; /* Максимальное число запросов, ожидающих обработки, установим равным 5 */ req.qlen = 5; /* Свяжем узел с запросом */ if (t_bind(tn, &req, (struct t_bind*)0) < 0) { t_error("Ошибка вызова t_bind(); exit(1); } fprintf(stderr, "Адрес сервера: %sn", inet_ntoa(serv_addr.sin_addr)); /* Поскольку в структуре t_call нам понадобится только буфер для хранения адреса клиента, разместим ее динамически */ if ((call = (struct t_call*)t_alloc(tn, T_CALL, T_ADDR)) == NULL) { t_error("Ошибка вызова t_alloc()"); exit(2); } call->addr.maxlen = sizeof(serv_addr); call->addr.len = sizeof(srv_addr); call->opt.len = 0; call->update.len = 0; /* Бесконечный цикл получения и обработки запросов */ while (1) { /* Ждем поступления запроса на установление соединения */ if (t_listen(s, call) < 0) { t_error("Ошибка вызова t_listen()"); exit(1); } /* Выведем информацию о клиенте, сделавшем запрос */ clnt_addr = (struct sockaddr_in*)call->addr.buf; printf("Клиент: %sn", inet_ntoa(clnt_addr->sin_addr)); /* Создадим транспортный узел для обслуживания запроса */ if (ntn = t_open("/dev/tcp", O_RDWR, (struct t_info*)0)) < 0) { t_error("Ошибка вызова t_open()"); exit(1); } /* Пусть система сама свяжет его с подходящим адресом */ if (t_bind(ntn, (struct t_bind*)0), (struct t_bind*)0) < 0) { t_error("Ошибка вызова t_accept()"); exit(1); } /* Примем запрос и переведем его обслуживание на новый транспортный узел */ if (t_accept(tn, ntn, call) < 0) { t_error("Ошибка вызова t_accept()"); exit(1); } /* Создадим новый процесс для обслуживания запроса. При этом родительский процесс продолжает принимать запросы от клиентов */ if ((pid = fork()) == -1) { t_error("Ошибка вызова fork()"); exit(1); } if (pid == 0) { int nbytes; /* Дочерний процесс: этот транспортный узел уже не нужен, он используется родителем */ close(tn); while ((nbytes = t_rcv(ntn, buf, sizeof(buf), &flags)) != 0) { t_snd(ntn, buf, sizeof(buf), 0); } t_close(ntn); exit(0); } /* Родительский процесс: этот транспортный узел не нужен, он используется дочерним процессом для обмена данными с клиентом */ t_close(ntn); } t_close(ntn);}Клиент
#include <sys/types.h>#include <sys/socket.h>#include <tiuser.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <fcntl.h>#include <netdb.h>#define PORTNUM 1500main(argc, argv)char *argv[];int argc;{
int tn; int flags; struct sockaddr_in serv_addr; struct hostent *hp; char buf[80]="Здравствуй, мир!"; struct t_call* call; /* В качестве аргумента клиенту передается доменное имя хоста, на котором запущен сервер. Произведем трансляцию доменного имени в адрес */ if ((hp = gethostbyname(argv[1])) == 0) {