UNIX: разработка сетевых приложений | страница 15
Переменную errno нельзя хранить как глобальную переменную в случае множества потоков, у которых все глобальные переменные являются общими. О решении этой проблемы мы расскажем в главе 23.
На протяжении всего текста книги мы использовали фразы типа «функция connect возвращает >ECONNREFUSED
» для сокращенного обозначения того, что при выполнении функции произошла ошибка (обычно при этом возвращаемое значение функции равно -1), и значение переменной >errno
стало равным указанной константе.
1.5. Простой сервер времени и даты
Мы можем написать простую версию сервера TCP для определения времени и даты, который будет работать с клиентом, описанным в разделе 1.2. Мы используем функции-обертки, описанные в предыдущем разделе. Код сервера приведен в листинге 1.5.
Листинг 1.5. TCP-сервер времени и даты
>//intro/daytimetcpsrv.c
> 1 #include "unp.h"
> 2 #include
> 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 }
>10
Создание сокета TCP выполняется так же, как и в клиентском коде.
>11-15
Заранее известный порт сервера (13 в случае сервера времени и даты) связывается с сокетом путем заполнения структуры адреса интернет-сокета и вызова функции >bind
. Мы задаем IP-адрес как >INADDR_ANY
, что позволяет серверу принимать соединение клиента на любом интерфейсе в том случае, если узел сервера имеет несколько интерфейсов. Далее мы рассмотрим, как можно ограничить прием соединений одним-единственным интерфейсом.
>16
С помощью вызова функции >listen
сокет преобразуется в прослушиваемый, то есть такой, на котором ядро принимает входящие соединения от клиентов. Эти три этапа, >socket
, >bind
и >listen
, обычны для любого сервера TCP при создании того, что мы называем