- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) - Сидни Фейт
Шрифт:
Интервал:
Закладка:
Вместо создания дочернего процесса для каждого клиента сервер может непосредственно выполнять запрос, а затем закрывать соединение. Очередь сервера позволяет нескольким другим клиентам ожидать, пока он не будет готов обработать их запросы.
Ниже приведен листинг для более простого сервера. К этому серверу клиенты также могут обращаться через рассмотренную выше программу tcpclient.
/* tcpsimp.c
* Для запуска программ ввести "tcpsimp" */
/* Сначала включить стандартные заголовочные файлы. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
main() {
int sockMain, sockClient, length, child;
struct sockaddr_in servAddr;
/* 1. Создать главный socket. */
if ( (sockMain = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Сервер не может открыть главный socket.");
exit(1);
}
/* 2. Ввести информацию в структуру данных, используемую для
* хранения локального IP-адреса и порта, "sin" в именах
* переменных — это сокращение от "socket internet". */
bzero((char *)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = 0;
/* 3. Вызвать bind, которая запишет используемый номер порта
* в servAddr. */
if (bind(sockMain, &servAddr, sizeof(servAddr)) ) {
perror("Вызов bind от сервера неудачен.");
exit(1);
}
/* 4. Чтобы узнать номер порта, следует использовать функцию
* getsockname() для копирования порта в servAddr. */
length = sizeof(servAddr);
if (getsockname(sockMain, &servAddr, &length)) {
perror("Вызов getsockname неудачен.");
exit(1);
}
printf ("SERVER: Номер порта %dn", ntohs(servAddr.sin_port));
/* 5. Установить очередь на пять клиентов.*/
listen(sockMain, 5);
/* 6. Ожидать поступления клиентов. Вызов accept возвратит
* дескриптор нового socket, который следует использовать клиенту. */
for(;;) {
if ((sockClient = accept(sockMain, 0, 0)) < 0) {
perror("Неверный socket клиента.");
exit(1);
}
/* 7. Обслужить клиента и закрыть соединение с ним. */
doTask(sockClient);
close(sockClient);
}
}
/* Читать один поступивший буфер, распечатать некоторую информацию
* и завершить работу. */
#define BUFLEN 81
int doTask(sockClient)
int sockClient;
{
char buf[BUFLEN];
int msgLength;
/* 8. Опустошение буфера и вызов recv
* для получения сообщения от клиента. */
bzero(buf, BUFLEN);
if ((msgLength = recv(sockClient,buf, 80, 0)) < 0) {
perror("Неверное получение." );
exit(1);
}
printf("SERVER: Socket для клиента %dn", sockClient);
printf("SERVER: Длина сообщения %dn", msgLength);
printf("SERVER: Сообщение: %snn", buf);
}
21.9 Интерфейс программирования socket для UDP
Мы познакомились с наиболее общим интерфейсом программирования TCP. Теперь рассмотрим программирование сервера и клиента UDP. На рис. 21.3 показана схема диалога UDP между клиентом и сервером. Вызовы socket() и bind() быстро выполняются и немедленно возвращают ответ. Вызов recvfrom предполагает режим блокирования по умолчанию, который можно изменить на неблокированный (т.е. асинхронный) режим.
Рис. 21.3. Типичные программные вызовы в socket UDP
21.10 Программа сервера UDP
Показанная ниже программа создает socket для UDP, связывает вызов с портом, а затем получает и распечатывает сообщения, которые посылаются на этот порт:
/* udpserv.c
* Для запуска программы ввести "udpserv".
*
* Сначала включить стандартные заголовочные файлы. */
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#define BUFLEN 81
main() {
int sockMain, addrLength, msgLength;
struct sockaddr_in servAddr, clientAddr;
char buf[BUFLEN];
/* 1. Создать socket для UDP. */
if ((sockMain = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Сервер не может открыть socket для UDP.");
exit(1);
}
/* 2. Ввести информацию в структуру данных, используемую для хранения локальных
* IP-адресов и порта. Возложить на bind получение свободных портов. */
bzero((char *)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = 0;
/* 3. Вызвать bind, которая запишет номер используемого порта
* в TCB. */
if (bind(sockMain, &servAddr, sizeof(servAddr))) {
perror("Вызов bind от сервера неудачен.");
exit(1);
}
/* 4. Извлекаем номер порта и используем функцию
* getsockname() для копирования порта в servAddr. */
addrLength = sizeof(servAddr);
if ( getsockname(sockMain, &servAddr, &addrLength)) {
perror(Вызов getsockname неудачен.");
exit(1);
}
printf("SERVER: Номер порта is %dn", ntohs(servAddr.sin_port));
/* 5. Бесконечный цикл ожидания сообщений от клиентов. */
for (;;) {
addrLength = sizeof(clientAddr);
bzero(buf, BUFLEN);
if ((msgLength = recvfrom(sockMain, buf, BUFLEN, 0, &clientAddr, &addrLength)) < 0) {
perror("Плохой socket клиента.");
exit(1);
}
/* 6. Распечатать клиентские IP-адрес и порт вместе с сообщением. */
printf("SERVER: IP-адрес клиента: %sn",
inet_ntoa(clientAddr.sin_addr));
printf("SERVER: Порт клиента: %dn",
ntohs(clientAddr.sin_port));
printf("SERVER: Длина сообщения %dn", msgLength);
printf("SERVER: Сообщение: %snn", buf);
}
}
21.10.1 Вызовы в серверной программе UDP
1. sockMain = socket(AF_NET, SOCK_DGRAM, 0);
Семейство адресов — снова Интернет.
2. bzero((char *)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = 0;
Вызовы инициализации адресной структуры сервера те же, что и в программе для TCP.
3. bind(sockMain, &servAddr, sizeof(servAddr));
Как и прежде, bind получает порт для сервера и записывает значения в TCB. Конечно, по сравнению с TCP, UDP содержит очень мало информации.
4. getsockname(sockMain, &servAddr, &length);
Использовать getsockname, чтобы извлечь присвоенный socket порт.
5. msgLength = recvfrom(sockMain, buf, BUFLEN, 0, &clientAddr, &length);
Вызов recvfrom имеет форму:
recvfrom(дескриптор_socket, входной_буфер, длина_буфера, флаги, исходная_адресная_структура, указатель_на_длину_исходной_адресной_структуры)
Флаги позволяют вызывающей стороне просмотреть сообщение без его фактического получения. После возвращения исходная адресная структура заполняется IP-адресом и номером порта клиента. Необходим указатель на длину исходного адреса, поскольку она может быть изменена при вставке в поле фактического адреса клиента.
6. inet_ntoa(clientAddr.sin_addr);
Этот вызов преобразует 32-разрядный адрес Интернета клиента в знакомую нам нотацию этого адреса с точками и десятичными значениями.
21.11 Клиентская программа UDP
Клиент соединяется с сервером, посылает одно сообщение и закрывает соединение. При запуске программы конечный пользователь должен ввести имя хоста, порт сервера и отправляемое на сервер сообщение. Например:
udpclient plum.cs.yale.edu 2315 "Это сообщение."
/* udpclient.с
* Перед запуском клиента следует запустить сервер.
* Далее нужно получить порт сервера.
* Для запуска клиента ввести:
* udpclient имя_хоста порт сообщение */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
main(argc, argv)
int argc;
char *argv[]; /* Это вводимые пользователем аргументы. */
/* argv[0] - имя программы. argv[1] указывает на имя хоста. */
/* argv[2] ссылается на порт, */
/* а argv [3] ссылается на текстовое сообщение. */