Introduction to client server networks

Составляющие клиент-серверной архитектуры

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

  1. Клиент — из названия становится понятно, что это пользователь сервиса (веб-приложения), который обращается к серверу для получения какой-то информации.

  2. Сервер — место, где располагается твое веб-приложение или его серверная часть. Он владеет необходимой информацией о пользователях или может ее запрашивать. Также при обращении клиента сервер возвращает ему запрашиваемую информацию.
  3. Сеть — все просто: обеспечивает обмен информацией между клиентом и сервером.

  • клиентского — содержит графический интерфейс для авторизации, отправки/получения сообщений;

  • серверного — веб-приложение, которое размещается на сервере и принимает сообщения от пользователей, обрабатывает их, а потом отправляет адресатам.

предыдущей части

Важно: понятие сервер — не о конкретном компьютере, а о взаимоотношениях абонентов сети.

Сжатие

Алгоритмы сжатия

  • Кодирование Хаффмана с заранее вычисленным кодом, которое чрезвычайно быстро и может давать хорошие результаты. Оно использовалось для сжатия пакетов в сетевом движке Quake3.
  • zlib — алгоритм сжатия общего назначения, который никогда не увеличивает объём данных. Как можно увидеть здесь, он применялся во множестве областей применения. Для обновления состояний он может оказаться избыточным. Но он может и пригодиться, если вам нужно отправлять клиентам с сервера ассеты, длинные тексты или рельеф.
  • Копирование длин серий — это, наверно, простейший алгоритм сжатия, но он очень эффективен для определённых типов данных, и может использоваться как этап предварительной обработки перед zlib. Он особенно подходит для сжатия рельефа, состоящего из тайлов или вокселей, в которых множество соседних элементов повторяется.

Дельта-сжатие

  • The Quake3 Networking Model Брайана Хука
  • Quake 3 Source Code Review: Network Model Фабьена Санглара

Snapshot Compression

Client-Server vs. Peer-to-Peer and Other Models

The client-server model of networking was initially developed to share access to database applications with many users. Compared to the mainframe model, client-server networking has better flexibility because connections can be made on-demand and as needed rather than being fixed.

The client-server model supports modular applications that can make the job of creating software easier. In the two-tier and three-tier types of client-server systems, software applications are separated into modular components, and each component is installed on clients or servers specialized for that subsystem.

Client-server networking is one approach to managing network applications. The primary alternative to client-server networking, peer-to-peer networking, treats all devices as having equivalent capability rather than specialized client or server roles.

Compared to client-server networks, peer-to-peer networks offer advantages such as flexibility in expanding the network to handle a large number of clients. Client-server networks offer advantages over peer-to-peer networks such as the ability to manage applications and data in a centralized location.

Трехуровневая архитектура

третий участник — хранилище данных

  1. Клиентский слой — интерфейс пользователя. Это может быть веб-браузер, которому отправляются HTML-страницы, или графическое приложение, написанное с помощью JavaFX. Главное, чтобы с его помощью пользователь мог отправлять запросы на сервер и обрабатывать его ответы.

  2. Слой логики — сервер, на котором происходит обработка запросов/ответов. Часто его еще называют серверным слоем. Также здесь происходят все логические операции: математические расчеты, операции с данными, обращения к другим сервисам или хранилищам данных.

  3. Слой данных — сервер баз данных: к нему обращается наш сервер. В этом слое сохраняется вся необходимая информация, которой пользуется приложение при работе.

TCP-сервер. Класс TcpListener

Последнее обновление: 31.10.2015

Класс TcpListener прослушивает входящие подключения по определенному порту.

Для создания объекта слушателя надо передать ему в конструктор объект IPAddress и порт, по которому будет вестись прослушивание входящих подключений:

IPAddress localAddr = IPAddress.Parse("127.0.0.1");
int port = 8888;
TcpListener server = new TcpListener(localAddr, port);
server.Start();

Для запуска сервера вызывается метод Start().

Когда к серверу обращается клиент, то мы можем использовать один из двух методов AcceptSocket или
AcceptTcpClient для получения соответственно объекта Socket или TcpClient,
которые будут использоваться для взаимодействия с подключенным клиентом.

TcpClient client = server.AcceptTcpClient();
// или
Socket socket = server.AcceptSocket();

Методы AcceptSocket и AcceptTcpClient блокируют выполняющий поток, пока сервер не обслужит подключенного клиента. Затем через методы, определенные
в классах TcpClient и Socket, можно взаимодействовать с подключенным клиентом: получать от него данные или, наоборот, отправлять ему.

В конце по завершению работы сервера надо вызвать метод Stop().

В прошлой теме был создан TCP-клиент. Теперь создадим примитивный TCP-сервер, к которому будет подключаться клиент:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TcpListenerApp
{
    class Program
    {
        const int port = 8888; // порт для прослушивания подключений
        static void Main(string[] args)
        {
            TcpListener server=null;
            try
            {
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");
                server = new TcpListener(localAddr, port);

                // запуск слушателя
                server.Start();

                while (true)
                {
                    Console.WriteLine("Ожидание подключений... ");

                    // получаем входящее подключение
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Подключен клиент. Выполнение запроса...");

                    // получаем сетевой поток для чтения и записи
                    NetworkStream stream = client.GetStream();

                    // сообщение для отправки клиенту
                    string response = "Привет мир";
					// преобразуем сообщение в массив байтов
                    byte[] data = Encoding.UTF8.GetBytes(response);

                    // отправка сообщения
                    stream.Write(data, 0, data.Length);
                    Console.WriteLine("Отправлено сообщение: {0}", response);
					// закрываем поток
					stream.Close();
                    // закрываем подключение
                    client.Close();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                if (server != null)
                    server.Stop();
            }
        }
    }
}

В данном случае сервер прослушивает все подключения по порту 8888. В бесконечном цикле он получает входящие подключения.

У входящих объектов TcpClient получает сетевой поток через метод и затем его использует для отправки сообщения.

И мы можем совместить клиента из прошлой темы с этим сервером. Тогда сервер будет отправлять клиентам данные, а клиенты — получать их.

НазадВперед

Выполнение основной функциональности на сервере

Вся работа с прикладными объектами, чтение и запись базы данных выполняется только на сервере. Функциональность форм и командного интерфейса также реализована на сервере.

На сервере выполняется подготовка данных форм, расположение элементов, запись данных форм после изменения. На клиенте отображается уже подготовленная на сервере форма, выполняется ввод данных и вызовы сервера для записи введенных данных и других необходимых действий.

Аналогично командный интерфейс формируется на сервере и отображается на клиенте. Также и отчеты формируются полностью на сервере и отображаются на клиенте.

При этом механизмы платформы ориентированы на минимизацию объема данных, передаваемых на клиентский компьютер. Например, данные списков, табличных частей и отчетов передаются с сервера не сразу, а по мере просмотра их пользователем.

На сервере выполняются:

  • Запросы к базе данных,
  • Запись данных,
  • Проведение документов,
  • Различные расчеты,
  • Выполнение обработок,
  • Формирование отчетов,
  • Подготовка форм к отображению.

На клиенте выполняется:

  • Получение и открытие форм,
  • Отображение форм,
  • «Общение» с пользователем (предупреждения, вопросы…),
  • Небольшие расчеты в формах, требующие быстрой реакции (например, умножение цены на количество),
  • Работа с локальными файлами,
  • Работа с торговым оборудованием.

Структура приложения

Мы не рассматриваем регистрацию, поиск контактов, хранение сообщений, продвинутый дизайн. Вместо этого вы узнаете азы создания клиент-серверных приложений и сможете сделать всё самостоятельно.

Исходный код мессенджера вы найдете на GitHub.

Приложение мы поделим на экраны:

  • экран авторизации;
  • экран с контактами;
  • экран с чатом.

Экран — это элемент Border, который по умолчанию скрыт от пользователя. Виден будет только активный экран.

На экране авторизации пользователь сможет ввести логин и пароль, чтобы войти. Если он ввёл верные данные, то перейдёт на экран с контактами, иначе — увидит сообщение об ошибке.

На экране с контактами видны имена других пользователей, с которыми ведётся переписка. Чат открывается при нажатии на имя другого пользователя.

Client-Server Applications

The client-server model organizes network traffic using a client application and client devices. Network clients send messages to a server to make requests of it. Servers respond to clients by acting on each request and returning the results. One server supports many clients, and multiple servers can be networked together in a server pool to handle increased processing loads as the number of clients grows.

A client computer and a server computer are two separate units of hardware, each customized for a designed purpose. For example, a web client works best with a large screen display, while a web server doesn’t need a display and can be located anywhere in the world. In some cases, however, a given device can function both as a client and a server for the same application. Additionally, a device that is a server for one application can simultaneously act as a client to other servers for different applications.

Рабочие нити RESTinio/Asio

Иногда пользователи RESTinio не задумываются о том, какие рабочие нити и как именно использует RESTinio. Например, кто-то может посчитать, что когда RESTinio запускается на одной рабочей нити (посредством , как в примере выше), то на этой рабочей нити RESTinio только вызывает обработчики запросов. Тогда как для операций ввода-вывода RESTinio «под капотом» создает отдельную нить. И эта отдельная нить продолжает обслуживать новые подключения когда основная рабочая нить занята request_handler-ом.

На самом деле все нити, которые пользователь выделяет RESTinio, используются и для выполнения операций ввода-вывода, и для вызова request_handler-ов. Поэтому, если вы запустили RESTinio-сервер через , то внутри на текущей нити будут выполняться и операции ввода-вывода, и обработчики запросов.

Грубо говоря, RESTinio запускает Asio-шный event-loop, внутри которого выполняется обработка новых подключений, чтение и парсинг данных из уже существующих подключений, запись готовых для отсылки данных, обработка закрытия соединений и т.п. Среди прочего, после того, как из очередного подключения вычитан и полностью разобран входящий запрос, для обработки этого запроса вызывается заданный пользователем request_handler.

Соответственно, если request_handler блокирует работу текущей нити, то блокируется и работающий на этой же нити Asio-шный event-loop. Все просто.

Если RESTinio запускается на пуле рабочих нитей (т.е. посредством , как вот в этом примере), то происходит практически тоже самое: на каждой нити из пула запускается Asio-шный event-loop. Поэтому если какой-то request_handler начнет перемножать большие матрицы, то это заблокирует рабочую нить в пуле и на этой нити перестанут обслуживаться операции ввода-вывода.

Поэтому при использовании RESTinio задача разработчика в том, чтобы его request_handler-ы завершались за разумное и, желательно, не очень большое время.

1-е Приложение клиент-сервер

Приложение состоит из двух программ. Клиентская программа, работающая на стороне клиента, и серверная программа, работающая на стороне сервера. Клиентская программа WishesClient.java отправляет серверу наилучшие пожелания, а серверная программа WishesServer.java получает сообщение и печатает на своем терминале (мониторе).

import java.net.Socket; 
import java.io.OutputStream;
import java.io.DataOutputStream;

public class WishesClient
{
   public static void main(String args[]) throws Exception
   {
     Socket sock = new Socket("127.0.0.1", 5000);       
     String message1 = "Accept Best Wishes, Serverji";

     OutputStream ostream = sock.getOutputStream();                 
     DataOutputStream dos = new DataOutputStream(ostream);
     dos.writeBytes(message1);                                                         
     dos.close();                            
     ostream.close();   
     sock.close();
  }
}
Socket sock = new Socket ("127.0.0.1", 5000);

Конструктор класса Socket принимает два параметра — строку, IP-адрес сервера и целое число, номер порта на сервере, к которому клиент хотел бы подключиться. 127.0.0.1 — это адрес по умолчанию локальной системы в компьютерных сетях.

Метод getOutputStream() класса Socket возвращает объект OutputStream, здесь объект является ostream. Это отправная точка всего общения (программы). Здесь сокет связан с потоками. Потоки способствуют передаче данных.

DataOutputStream dos = new DataOutputStream (ostream);
dos.writeBytes (message1);

OutputStream является абстрактным классом; он не может быть использован напрямую. В приведенном выше коде он связан с конкретным классом DataOutputStream. Метод writeBytes() объекта DataOutputStream принимает строковое сообщение и передает его в Socket. Теперь клиентский сокет отправляется на другой сокет на сервере. Когда работа закончится, закройте потоки и сокет. Он освобождает дескрипторы (ссылки), связанные с системными ресурсами.

Ниже приведены исключения в вышеприведенной программе, создаваемые конструктором и различными методами.

  • Socket(«127.0.0.1», 5000) выдает UnknownHostException
  • getOutputStream() генерирует IOException
  • writeBytes (message1) выдает IOException
  • Все методы close() выдают IOException
  • Серверная программа — WishesServer.java
import java.net.ServerSocket;            
import java.net.Socket;            
import java.io.InputStream;
import java.io.DataInputStream;

public class WishesServer
{
   public static void main(String args[]) throws Exception
   {
     ServerSocket sersock = new ServerSocket(5000); 
     System.out.println("server is ready");  //  message to know the server is running

     Socket sock = sersock.accept();               
                                                                                          
     InputStream istream = sock.getInputStream();  
     DataInputStream dstream = new DataInputStream(istream);

     String message2 = dstream.readLine();
     System.out.println(message2);
     dstream .close(); istream.close(); sock.close(); sersock.close();
  }
}

У сервера есть два задания: одно, как и ожидалось, должно связываться, а другое связывает соединение с номером порта 5000. Для связи он использует Socket, а для привязки — ServerSocket.

accept() — это метод класса ServerSocket, используемый сервером для привязки соединения по номеру порта 5000, запрошенного клиентом.

Метод getInputStream() объекта Socket возвращает объект InputStream, и это отправная точка серверной программы. Сервер использует входной поток при получении сообщения.

Поскольку InputStream является абстрактным классом, его нельзя использовать напрямую. Он связан с конкретным классом DataInputStream.

Метод readLine() объекта DataInputStream читает строку сообщения из сокета и возвращает ее. Это сообщение печатается на консоли.

Реализация MCU

Критики использования полноценных MCU в качестве их главного недостатка называют высокую стоимость. Этот стереотип, сложившийся десятилетия назад, уже давно устарел и перестал быть актуальным. Но, к сожалению, даже специалисты до сих пор иногда путают архитектуры систем ВКС с конкретной реализацией сервера MCU. Пять-десять лет назад для выполнения ресурсоемких операций по обработке видео (транскодирование, трансрейтинг, микширование) требовалось действительно очень дорогое аппаратное обеспечение. Кроме того, на рынке было мало предложений, слабая конкуренция, что не способствовало снижению цен.

Однако за прошедшие годы технический прогресс привел к значительному росту вычислительных и графических мощностей даже недорогих серверов стандартной архитектуры. Поэтому полный функционал MCU сегодня эффективно реализуется на базе стандартных серверных платформ с доступными графическими процессорами. Не требуются ни дорогостоящие DSP-процессоры, ни другие сложные аппаратные элементы. Всё это позволило производителям предложить действительно эффективные полноценные MCU по относительно невысокой цене. Причем дополнительные инфраструктурные элементы, такие как сервер регистрации, сервер записи и трансляции видео могут быть реализованы в виде дополнительных программных модулей, которые устанавливаются на тот же сервер. Уже не требуются отдельные физические серверы для регистрации, записи и трансляции, что также снижает стоимость полного решения для системы ВКС.

Даже если вам сегодня предлагают дорогостоящий выполненный в виде специализированного устройства сервер MCU, может оказаться, что у него «под капотом» обычный компьютер x86. И стоит такой компьютер на порядок меньше той суммы, что просят за так называемое «специализированное устройство».

Еще раз повторим важный момент. Независимо от архитектуры системы (централизованная или распределенная), реализация сервера может быть различной: специализированная аппаратно-программная платформа или ПО для стандартного сервера, в том числе для работы в виртуализированной среде. Не верьте тому, что для централизованной системы в качестве полноценного MCU обязательно необходим дорогой специализированный аппаратно-программный комплекс, а для распределенной – достаточно недорогого ПО. Это миф. На рынке имеются эффективные полноценные MCU, выполненные в виде ПО для стандартной серверной платформы.

Преимущества трехуровневой архитектуры

  1. Возможность построить защиту от SQL-инъекций — это атака на сервер, при которой передается SQL-код, и при выполнении этого кода злоумышленник может воздействовать на нашу базу данных.

  2. Разграничение данных, к которым мы хотим регулировать пользовательский доступ.

  3. Возможность модифицировать данные перед отправкой клиенту.

  4. Масштабируемость — возможность расширить наше приложение на несколько серверов, которые будут использовать одну и ту же базу данных.

  5. Меньшие требования к качеству соединения пользователя. Формируя ответ на сервере, мы часто берем из базы данных много различной информации, форматируем ее, оставляя только то, что нужно юзеру. Таким образом мы сокращаем объем информации, который отправим в качестве ответа клиенту.

Для чего нужен сервер

Для того, чтобы ответить на вопрос «для чего нужен сервер», необходимо знать несколько основных задач применения:

1. Выполнение отдельных технический функций. В данном случае, речь может идти абсолютно о чем угодно. Это могут быть сервера под хостинг. Это могут быть игровые сервера. Это могут быть почтовые сервера и все что угодно.

Примечание: Если вас интересует практический пример использования, то советую так же ознакомиться со статьей Устройство DNS сервера и узнать как устроена интернет адресация (как браузер находит сайт и страницы).

2. Файловое хранилище. Как и следует из названия, речь идет о решении банального вопроса хранения данных. Например, какой смысл с собой на ноутбуке постоянно таскать вашу медиатеку с фильмами и музыкой, если они вам нужны только в домашних условиях. Проще их хранить на отдельном компьютере и по мере необходимости использовать или загружать частями.

3. Бесперебойность доступа к чему-либо. Представьте, что у вас обычный компьютер, в котором в каталоге с общим доступом хранятся какие-то файлы. Или же может быть, что через ваш компьютер осуществляется доступ в интернет. Что будет если его выключить? Правильно, доступа к файлам или интернету не будет. Вот для решения подобных задач применяются сервера. То есть нет необходимости заново включать компьютер и ждать время, за которое будет загружаться операционная система и запускаться все необходимые программы.

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

1
1
1
1
1
1
1
1
1
1

Рейтинг 0.00 (0 Голосов)

Хотите выразить благодарность автору? Поделитесь с друзьями!

  • Что такое хэштег?
  • Что такое оптимизация?
  • Что такое хэштег?
    Что такое?

  • Что такое Хэш?
    Что такое?

  • Что такое стек?
    Что такое?

  • Что такое оптимизация?
    Что такое?

  • Что такое ping?
    Что такое?

  • Что такое репост?
    Что такое?

Добавить комментарий / отзыв

Комментарий — это вежливое и наполненное смыслом сообщение (правила).

Имя (обязательное)

E-Mail

Подписаться на уведомления о новых комментариях

Отправить
Отменить

* Нажимая на кнопку «Отправить», Вы соглашаетесь с политикой конфиденциальности.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *