UNIX: разработка сетевых приложений | страница 15



. Ни одна ошибка не имеет кода 0.

Переменную 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 }

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

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

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

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

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

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