Литмир - Электронная Библиотека
Содержание  
A
A

19-24
 Для каждого клиента функция
fork
порождает дочерний процесс, и дочерний процесс обслуживает запрос этого клиента. Как мы говорили в разделе 4.8, дочерний процесс закрывает прослушиваемый сокет, а родительский процесс закрывает присоединенный сокет. Затем дочерний процесс вызывает функцию
str_echo
(см. листинг 5.2) для обработки запроса клиента.

5.3. Эхо-сервер TCP: функция str_echo

Функция

str_echo
, показанная в листинге 5.2, выполняет серверную обработку запроса клиента: считывание строк от клиента и отражение их обратно клиенту.

Листинг 5.2. Функция str_echo: отраженные строки на сокете

//lib/str_echo.c

 1 #include "unp.h"

 2 void

 3 str_echo(int sockfd)

 4 {

 5  ssize_t n;

 6  char buf[MAXLINE];

 7  for (;;) {

 8   if ((n = read(sockfd, buf, MAXLINE)) > 0)

 9    return; /* соединение закрыто с другого конца */

10   Writen(sockfd, line, n);

11  }

12 }

Чтение строки и ее отражение

7-11
 Функция
read
считывает очередную строку из сокета, после чего строка отражается обратно клиенту с помощью функции
writen
. Если клиент закрывает соединение (нормальный сценарий), то при получении клиентского сегмента FIN функция дочернего процесса
read
возвращает нуль. После этого происходит возврат из функции
str_echo
и далее завершается дочерний процесс, приведенный в листинге 5.1.

5.4. Эхо-клиент TCP: функция main

В листинге 5.3 показана функция

main
TCP-клиента.

Листинг 5.3. Эхо-клиент TCP

//tcpcliserv/tcpcli01.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int sockfd;

 6  struct sockaddr_in servaddr;

 7  if (argc != 2)

 8   err_quit("usage: tcpcli <Ipaddress>");

 9  sockfd = Socket(AF_INET, SOCK_STREAM, 0);

10  bzero(&servaddr. sizeof(servaddr));

11  servaddr.sin_family = AF_INET;

12  servaddr.sin_port = htons(SERV_PORT);

13  Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

14  Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));

15  str_cli(stdin, sockfd); /* эта функция выполняет все необходимые

                               действия со стороны клиента */

16  exit(0);

17 }

Создание сокета, заполнение структуры его адреса

9-13
 Создается сокет TCP и структура адреса сокета заполняется IP-адресом сервера и номером порта. IP-адрес сервера мы берем из командной строки, а известный номер порта сервера (
SERV_PORT
) — из нашего заголовочного файла
unp.h
.

Соединение с сервером

14-15
 Функция
connect
устанавливает соединение с сервером. Затем функция
str_cli
(см. листинг 5.4) выполняет все необходимые действия со стороны клиента.

5.5. Эхо-клиент TCP: функция str_cli

Эта функция, показанная в листинге 5.4, обеспечивает отправку запроса клиента и прием ответа сервера в цикле. Функция считывает строку текста из стандартного потока ввода, отправляет ее серверу и считывает отраженный ответ сервера, после чего помещает отраженную строку в стандартный поток вывода.

Листинг 5.4. Функция str_cli: цикл формирования запроса клиента

//lib/str_cli.c

 1 #include "unp.h"

 2 void

 3 str_cli(FILE *fp, int sockfd)

 4 {

 5  char sendline[MAXLINE], recvline[MAXLINE];

 6  while (Fgets(sendline, MAXLINE, fp) != NULL) {

 7   Writen(sockfd,. sendline, strlen(sendline));

 8   if (Readline(sockfd, recvline, MAXLINE) == 0)

 9    err_quit("str_cli: server terminated prematurely");

10   Fputs(recvline, stdout);

11  }

12 }

Считывание строки, отправка серверу

6-7
 Функция
fgets
считывает строку текста, а функция
writen
отправляет эту строку серверу.

Считывание отраженной сервером строки, запись в стандартный поток вывода

8-10
 Функция
readline
принимает отраженную сервером строку, а функция
fputs
записывает ее в стандартный поток вывода.

Возврат в функцию main

11-12
 Цикл завершается, когда функция
fgets
возвращает пустой указатель, что означает достижение конца файла или обнаружение ошибки. Наша функция-обертка
Fgets
проверяет наличие ошибки, и если ошибка действительно произошла, прерывает выполнение программы. Таким образом, функция
Fgets
возвращает пустой указатель только при достижении конца файла.

49
{"b":"225366","o":1}