Skip to content

Latest commit

 

History

History
97 lines (66 loc) · 4.09 KB

File metadata and controls

97 lines (66 loc) · 4.09 KB

Клиент-серверная архитектура

В сети правит клиент-серверная архитектура. Всё в сети работает так: клиентский процесс обращается к сереверному процессу и наоборот.

Пример цикла общения между клиентом и сервером в интернете:

  1. Клиент отправляет запрос серверу, через send()
  2. Сервер получает запрос клиента, через recv()
  3. Сервер отправляет ответ клиенту, через send()
  4. Клиент получает ответ сервера, через recv()

Как видно, и сервер и клиент общаются через сокеты, записывая и считывая данные вызовами send() и recv().

Обычно сервер и клиент общаются через TCP или UDP - SOCK_STREAM или SOCK_DGRAM соответственно.

Простой TCP-сервер

Реализуем простой сервер, который просто отвечает строкой "Hello World".

Исходный код:

tcp/server.c

Проверить работу, можно с помощью утилиты telnet:

$ telnet localhost 3490
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World!Connection closed by foreign host.

В этой программе используется многопроцессность для неблокирующей обработки запросов, через функцию fork(). По завершению дочерних процессов из функции fork() остаются процессы-зомби, которые нужно очистить.

Очистка процессов-зомби происходит в обработчике сигнала выхода из процесса:

/* обработчик сигнала завершения дочернего процесса */
void sigchld_handler(int s)
{
	/* скрываем unused предупреждение */
	(void)s; 

	/* сохраняем errno, чтобы основной код остался не тронутым, после чистки */
	int saved_errno = errno;

	/* безопасная, неблокирующая, чистка зомби-процессов */
	while( waitpid( -1, NULL, WNOHANG ) > 0 );
	
	/* восстанавливаем errno */
	errno = saved_errno;
}

Зомби-процессы нужно очищать, иначе они забивают таблицу процессов и висят там беконечно:

  • Усложняют работу ОС.
  • Блокируют записи в таблице процессов, размер которой ограничен.

Простой TCP-клиент

Клиент по содержанию проще ,чем сервер. Ему всего-лишь нужно подключиться к хосту с портом и получить сообщение от сервера.

Исходный код:

tcp/client.c

Запустив сервер, можно обратится к нему этим клиентом:

1. Запуск сервера

$ ./server
server: waiting for connections...

2. Запуск клиента

$ ./client 127.0.0.1
client: attempting connection to 127.0.0.1
client: connected to 127.0.0.1
client: received 'Hello World!'

Как видим, клиент получил сообщение от сервера - Hello World!.

Если сервер не был запущен, то клиент напишет, что в подключении было отказано:

$ ./client localhost
client: attempting connection to 127.0.0.1
client: connect: Connection refused
client: failed to connect