30.3. Тестовый клиент TCP

We use cookies. Read the Privacy and Cookie Policy

30.3. Тестовый клиент TCP

В листинге 30.1[1] показан клиент, который будет использоваться для тестирования всех вариаций нашего сервера.

Листинг 30.1. Код клиента TCP для проверки различных версий сервера

//server/client.с

 1 #include "unp.h"

 2 #define MAXN 16384 /* максимальное количество байтов, которые могут быть

                         запрошены клиентом от сервера */

 3 int

 4 main(int argc, char **argv)

 5 {

 6  int i, j, fd, nchildren, nloops, nbytes;

 7  pid_t pid;

 8  ssize_t n,

 9   char request[MAXLINE], reply[MAXN];

10  if (argc != 6)

11   err_quit("usage: client <hostname or IPaddr> <port> <#children> "

12    "<#loops/child> <#bytes/request>");

13  nchildren = atoi(argv[3]);

14  nloops = atoi(argv[4]);

15  nbytes = atoi(argv[5]);

16  snprintf(request, sizeof(request), "%d ", nbytes); /* в конце

                                            символ новой строки */

17  for (i = 0; i < nchildren; i++) {

18   if ((pid = Fork()) == 0) { /* дочерний процесс */

19    for (j = 0; j < nloops; j++) {

20     fd = Tcp_connect(argv[1], argv[2]);

21     Write(fd, request, strlen(request));

22     if ((n = Readn(fd, reply, nbytes)) != nbytes)

23      err_quit("server returned %d bytes", n);

24     Close(fd); /* состояние TIME_WAIT на стороне клиента,

                     а не сервера */

25    }

26    printf("child %d done ", i);

27    exit(0);

28   }

29   /* родительский процесс снова вызывает функцию fork */

30  }

31  while (wait(NULL) > 0) /* теперь родитель ждет завершения всех

                              дочерних процессов */

32   ;

33  if (errno != ECHILD)

34   err_sys("wait error");

35  exit(0);

36 }

10-12 Каждый раз при запуске клиента мы задаем имя узла или IP-адрес сервера, порт сервера, количество дочерних процессов, порождаемых функцией fork (что позволяет нам инициировать несколько одновременных соединений с сервером), количество запросов, которое каждый дочерний процесс должен посылать серверу, и количество байтов, отправляемых сервером в ответ на каждый запрос.

17-30 Родительский процесс вызывает функцию fork для порождения каждого дочернего процесса, и каждый дочерний процесс устанавливает указанное количество соединений с сервером. По каждому соединению дочерний процесс посылает запрос, задавая количество байтов, которое должен вернуть сервер, а затем дочерний процесс считывает это количество данных с сервера. Родительский процесс просто ждет завершения выполнения всех дочерних процессов. Обратите внимание, что клиент закрывает каждое соединение TCP, таким образом состояние TCP TIME_WAIT имеет место на стороне клиента, а не на стороне сервера. Это отличает наше клиент-серверное соединение от обычного соединения HTTP.

При тестировании различных серверов из этой главы мы запускали клиент следующим образом:

% client 192.168.1.20 8888 5 500 4000

Таким образом создается 2500 соединений TCP с сервером: по 500 соединений от каждого из 5 дочерних процессов. По каждому соединению от клиента к серверу посылается 5 байт ("4000 "), а от сервера клиенту передается 4000 байт. Мы запускаем клиент на двух различных узлах, соединяясь с одним и тем же сервером, что дает в сумме 5000 соединений TCP, причем максимальное количество одновременных соединений с сервером в любой момент времени равно 10.

ПРИМЕЧАНИЕ

Для проверки различных веб-серверов существуют изощренные контрольные тесты. Один из них называется WebStone. Информация о нем находится в свободном доступе по адресу http://www.mindcraft.com/webstone. Для общего сравнения различных альтернативных устройств сервера, которые мы рассматриваем в этой главе, нам не нужны столь сложные тесты.

Теперь мы представим девять различных вариантов устройства сервера.

Данный текст является ознакомительным фрагментом.