Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

Листинг 1.5. TCP-сервер времени и даты

//intro/daytimetcpsrv.c

1 #include "unp.h"

2 #include <time.h>

3 int

4 main(int argc, char **argv)

5 {

6 int listenfd, connfd;

7 struct sockaddr_in servaddr;

8 char buff[MAXLINE];

9 time_t ticks;

10 listenfd = Socket(AF_INET, SOCK_STREAM, 0);

11 bzero(&servaddr, sizeof(servaddr));

12 servaddr.sin_family = AF_INET;

13 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

14 servaddr.sin_port = htons(13); /* сервер времени и даты */

15 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));

16 Listen(listenfd, LISTENQ);

17 for (;;) {

18 connfd = Accept(listenfd, (SA*)NULL, NULL);

19 ticks = time(NULL);

20 snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

21 Write(connfd. buff, strlen(buff));

22 Close(connfd);

23 }

24 }

Создание сокета TCP

10
Создание сокета TCP выполняется так же, как и в клиентском коде.

Связывание заранее известного порта сервера с сокетом

11-15
Заранее известный порт сервера (13 в случае сервера времени и даты) связывается с сокетом путем заполнения структуры адреса интернет-сокета и вызова функции
bind
. Мы задаем IP-адрес как
INADDR_ANY
, что позволяет серверу принимать соединение клиента на любом интерфейсе в том случае, если узел сервера имеет несколько интерфейсов. Далее мы рассмотрим, как можно ограничить прием соединений одним-единственным интерфейсом.

Преобразование сокета в прослушиваемый сокет

16
С помощью вызова функции
listen
сокет преобразуется в прослушиваемый, то есть такой, на котором ядро принимает входящие соединения от клиентов. Эти три этапа,
socket
,
bind
и
listen
, обычны для любого сервера TCP при создании того, что мы называем прослушиваемым дескриптором( listening descriptor) (в нашем примере это переменная
listenfd
).

Константа

LISTENQ
взята из нашего заголовочного файла
unp.h
. Она задает максимальное количество клиентских соединений, которые ядро ставит в очередь на прослушиваемом сокете. Более подробно мы расскажем о таких очередях в разделе 4.5.

Прием клиентского соединения, отправка ответа

17-21
Обычно процесс сервера блокируется при вызове функции
accept
, ожидая принятия подключения клиента. Для установки TCP-соединения используется трехэтапное рукопожатие( three-way handshake). Когда рукопожатие состоялось, функция accept возвращает значение, и это значение является новым дескриптором (
connfd
), который называется присоединенным дескриптором( connected descriptor). Этот новый дескриптор используется для связи с новым клиентом. Новый дескриптор возвращается функцией
accept
для каждого клиента, соединяющегося с нашим сервером.

ПРИМЕЧАНИЕ

Стиль, используемый в книге для обозначения бесконечного цикла, выглядит так:

for (;;) {

...

}

Библиотечная функция

time
возвращает количество секунд с начала эпохи Unix: 00:00:00 1 января 1970 года UTC (Universal Time Coordinated — универсальное синхронизированное время, среднее время по Гринвичу). Следующая библиотечная функция,
ctime
, преобразует целочисленное значение секунд в строку следующего формата, удобного для человеческого восприятия:

Fri Jan 12 14:27:52 1996

Возврат каретки и пустая строка добавляются к строке функцией

snprintf
, а результат передается клиенту функцией
write
.

ПРИМЕЧАНИЕ

Если вы еще не выработали у себя привычку пользоваться функцией snprintf вместо устаревшей sprintf, сейчас самое время заняться этим. Функция sprintf не в состоянии обеспечить проверку переполнения буфера получателя. Функция snprintf, наоборот, требует, чтобы в качестве второго аргумента указывался размер буфера получателя, переполнение которого таким образом предотвращается.

Функция snprintf была добавлена в стандарт ANSI С относительно нравно, в версии ISO C99. Практически все поставщики программного обеспечения уже сейчас включают эту функцию в стандартную библиотеку языка С. Существуют и свободно распространяемые реализации. В нашей книге мы используем функцию snprintf и рекомендуем вам пользоваться ею в своих программах для повышения их надежности.

Удивительно много сетевых атак было реализовано хакерами с использованием незащищенности sprintf от переполнения буфера. Есть еще несколько функций, с которыми нужно быть аккуратными: gets, strcat и strcpy. Вместо них лучше использовать fgets, strncat и strncpy. Еще лучше работают более современные функции strlcat и strlcpy, возвращающие в качестве результата правильно завершенную строку. Полезные советы, касающиеся написания надежных сетевых программ, можно найти в главе 23 книги [32].

  • Читать дальше
  • 1
  • ...
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: