Как написать программу для сервера

Сегодня мы рассмотрим пример программирования сокетов Python. Мы создадим серверные и клиентские приложения на Python.

Программирование сокетов

Чтобы понять программирование сокетов Python, нам нужно знать о трех интересных темах – Socket Server, Socket Client и Socket.

Итак, что такое сервер? Сервер – это программное обеспечение, которое ожидает запросов клиентов и обслуживает или обрабатывает их соответственно.

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

Socket – это конечная точка двунаправленного канала связи между сервером и клиентом. Сокеты могут обмениваться данными внутри процесса, между процессами на одной машине или между процессами на разных машинах. Для любого взаимодействия с удаленной программой мы должны подключаться через порт сокета.

Основная цель этого руководства по программированию сокетов – познакомить вас с тем, как сервер сокетов и клиент взаимодействуют друг с другом. Вы также узнаете, как написать программу сервера сокетов в Python.

Сокеты в программировании. Пишем свой сервер и клиент.

Пример

Ранее мы говорили, что клиент сокета запрашивает некоторые ресурсы у сервера, и сервер отвечает на этот запрос.

Итак, мы разработаем и серверную, и клиентскую модель, чтобы каждый мог общаться с ними. Шаги можно рассматривать так:

  1. Программа сервера сокетов запускается сначала и ждет любого запроса.
  2. Клиентская программа сначала инициирует диалог.
  3. Затем серверная программа будет реагировать на запросы клиента соответственно.
  4. Клиентская программа будет завершена, если пользователь введет сообщение «до свидания». Серверная программа также завершится, когда завершится клиентская программа, это необязательно, и мы можем поддерживать выполнение серверной программы на неопределенный срок или завершить работу с помощью какой-либо конкретной команды в клиентском запросе.

Сервер сокетов

Веб-сервер на C++ и сокетах

Создадим HTTP-сервер, который обрабатывает запросы браузера и возвращает ответ в виде HTML-страницы.

  • Введение в HTTP
  • Что будет делать сервер?
  • О сокетах
  • Создание сокета
  • Привязка сокета к адресу (bind)
  • Подготовка сокета к принятию входящих соединений (listen)
  • Ожидание входящего соединения (accept)
  • Получение запроса и отправка ответа
  • Последовательная обработка запросов

Введение в HTTP

Для начала разберемся, что из себя представляет HTTP. Это текстовый протокол для обмена данными между браузером и веб-сервером.

Пример HTTP-запроса:

GET /page.html HTTP/1.1 Host: site.com

Первая строка передает метод запроса, идентификатор ресурса (URI) и версию HTTP-протокола. Затем перечисляются заголовки запроса, в которых браузер передает имя хоста, поддерживаемые кодировки, cookie и другие служебные параметры. После каждого заголовка ставится символ переноса строки rn .

Socket или как создать собственный сервер на Python в домашних условиях #1 | Базовый курс Python

У некоторых запросов есть тело. Когда отправляется форма методом POST, в теле запроса передаются значения полей этой формы.

Иногда необходимо передать данные в другом формате. Например, при загрузке файлов на сервер, бинарные данные кодируются методом «multipart/form-data».

Читайте также:
Как делать заявки в программе 1с

Сервер обрабатывает запрос клиента и возвращает ответ.

Пример ответа сервера:

HTTP/1.1 200 OK Host: site.com Content-Type: text/html; charset=UTF-8 Connection: close Content-Length: 21

Test page.

В первой строке ответа передается версия протокола и статус ответа. Для успешных запросов обычно используется статус «200 OK». Если ресурс не найден на сервере, возвращается «404 Not Found».

Тело ответа так же, как и у запроса, отделяется от заголовков одной пустой строкой.

Полная спецификации протокола HTTP описывается в стандарте rfc-2068. По понятным причинам, мы не будем реализовывать все возможности протокола в рамках этого материала. Достаточно реализовать поддержку работы с заголовками запроса и ответа, получение метода запроса, версии протокола и URL-адреса.

Что будет делать сервер?

Сервер будет принимать запросы клиентов, парсить заголовки и тело запроса, и возвращать тестовую HTML-страничку, на которой отображены данные запроса клиента (запрошенный URL, метод запроса, cookie и другие заголовки).

Пример ответа от сервера

О сокетах

Для работы с сетью на низком уровне традиционно используют сокеты. Сокет — это абстракция, которая позволяет работать с сетевыми ресурсами, как с файлами. Мы можем писать и читать данные из сокета почти так же, как из обычного файла.

В этом материале мы будем работать с виндовой реализацией сокетов, которая находится в заголовочном файле . В Unix-подобных ОС принцип работы с сокетами такой же, только отличается API. Вы можете подробнее почитать о сокетах Беркли, которые используются в GNU/Linux.

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

Создадим сокет с помощью функции socket , которая находится в заголовочном файле . Для работы с IP-адресами нам понадобится заголовочный файл .

#include #include #include // Для корректной работы freeaddrinfo в MinGW // Подробнее: http://stackoverflow.com/a/20306451 #define _WIN32_WINNT 0x501 #include #include // Необходимо, чтобы линковка происходила с DLL-библиотекой // Для работы с сокетам #pragma comment(lib, «Ws2_32.lib») using std::cerr; int main() < // служебная структура для хранение информации // о реализации Windows Sockets WSADATA wsaData; // старт использования библиотеки сокетов процессом // (подгружается Ws2_32.dll) int result = WSAStartup(MAKEWORD(2, 2), // Если произошла ошибка подгрузки библиотеки if (result != 0) < cerr struct addrinfo* addr = NULL; // структура, хранящая информацию // об IP-адресе слущающего сокета // Шаблон для инициализации структуры адреса struct addrinfo hints; ZeroMemory( // AF_INET определяет, что используется сеть для работы с сокетом hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; // Задаем потоковый тип сокета hints.ai_protocol = IPPROTO_TCP; // Используем протокол TCP // Сокет биндится на адрес, чтобы принимать входящие соединения hints.ai_flags = AI_PASSIVE; // Инициализируем структуру, хранящую адрес сокета — addr. // HTTP-сервер будет висеть на 8000-м порту локалхоста result = getaddrinfo(«127.0.0.1», «8000», addr); // Если инициализация структуры адреса завершилась с ошибкой, // выведем сообщением об этом и завершим выполнение программы if (result != 0) < cerr // Создание сокета int listen_socket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); // Если создание сокета завершилось с ошибкой, выводим сообщение, // освобождаем память, выделенную под структуру addr, // выгружаем dll-библиотеку и закрываем программу if (listen_socket == INVALID_SOCKET) < cerr // .

Читайте также:
Какие вкладки с инструментами содержит программа Microsoft word ответ

Как написать программу для сервера

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

1. Нужно хорошо ориентироваться в терминологии локальных сетей, многоуровневой модели OSI (которая и так достаточно запутана — многие технологии и протоколы относятся сразу к нескольким уровням) многообразии сетевых технологий, в методах адресации — чтобы подобрать оптимальные протоколы работы приложения. Однако, наиболее распространен, без всяких сомнений, TCP/IP.

2. На каждой платформе свои обёртки к сетевому IP. Например, в MFC (Visual Studio) это CSocket, в Delphi TSocket, TServerSocket, TClientSocket. Простые примеры из help или Интернета обычно работают нормально, но если надо что-то переделать — перехватить ошибки, организовать обработку множества одновременных подключений к серверу — обёртки только усложняют задачу, и хороший/понятный пример найти уже сложнее.

3. Качественное применение обёрток подразумевает Ваше хотя бы приблизительное знакомство с базовыми функциями и принципами работы библиотеки Windows Sockets — иначе будет трудно понять и применить многие свойства и методы обёрток (связанные, например, с блокирующими функциями Windows Sockets).

4. Если Вы решили отказаться от оберток в пользу прямого вызова функций Windows Sockets (хороший выбор!) — будьте готовы к тому, что потребуются хорошие знания по написанию многопоточных приложений, методам корректного выделения и освобождения памяти, функциям обратного вызова (callback), межпотоковым взаимодействиям и т. п. Всё это потому, что многие функции Windows Sockets блокируют ход выполнения программы.

5. Для написания Winsock-приложения можно использовать пять моделей управления вводом-выводом (select, WSAAsyncSelect, WSAEventSelect, перекрытый ввод-вывод и порты завершения). Разобраться в этих технологиях и выбрать для себя одну (или несколько) может оказаться непростым делом.

Из всего вышесказанного ясно, что у “новичка в чистом виде” практически никаких шансов написать что-то путное, которое будет работать хотя бы с самыми щадящими требованиями к надежности и быстродействию. Если Вы — стреляный воробей, любите C (не купились сомнительной лёгкостью Visual Basic и Delphi), и успели слегка попробовать и то, и это (с переменным успехом), но понимания в сетевом программировании ещё не достигли, хотите чего-то большего, неплохо бы прочитать хотя бы разок хорошую книжку по предмету.

Лучшая из тех, что мне попадалась — “Программирование в сетях Windows” Э. Джонс, Д. Оланд, издательство Microsoft Press 2002 года — ни капли лишнего, максимально широко рассмотрена тема (в пределах разумного), много хороших работоспособных примеров (на CD-ROM). Самое оно. Прочитаете, и сразу полегчает, останется только написать программу. Вам пока только кажется, что все понятно, не обольщайтесь — придётся ещё не раз перечитывать в книге многие места.

Читайте также:
Прекращена работа программы speed2 exe

Напоследок приведу по шагам алгоритм работы сервера, который может одновременно обслуживать множество клиентских подключений. Исходный код можно скачать по ссылкам [1, 2] (проекты Win32 Console Visual C++). Первая программа может соединять сессии telnet с COM-портом. Вторая — консольный сервер telnet.

Писать многопоточный сервер предлагаю в такой последовательности:

1. Нужно загрузить правильную версию библиотеки Winsock. Я пользовался версией 2.0, хотя уже существует версия 2.2. Делается это так:

WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested,

Если err не равно 0, то произошла ошибка (err содержит код ошибки, который можно расшифровать подпрограммой WSA_Err_Decode). В случае ошибки завершаем программу.

2 [можно пропустить]. Проверяем версию загруженной библиотеки. Она должна равняться запрашиваемой.

if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) < WSACleanup( ); WLog («Couldn’t find a usable WinSock DLL»); //далее идёт код, который обеспечивает завершение программы по ошибке >

3 [можно пропустить]. Получение информации о том, сколько нужно памяти для опроса протоколов.

4 [можно пропустить]. WSAGetLastError() должна вернуть WSAENOBUFS.

5 [можно пропустить]. Выделение памяти для опроса протоколов.

6 [можно пропустить]. Загрузка в память информации о протоколах.

7 [можно пропустить]. Опрос всех доступных протоколов и поиск среди них нужного (в моей программе используется TCP/IP, и условие будет

(wsapi->iAddressFamily == AF_INET) (wsapi->iProtocol == IPPROTO_TCP)).

8. Создание сокета, который будет принимать соединения вызовом WSASocket. Если WSASocket вернул INVALID_SOCKET, то получаем код ошибки по WSAGetLastError и завершаем программу. Код ошибки можно расшифровать подпрограммой WSA_Err_Decode.

9. Привязка сокета к адресу (bind). Для того, чтобы сервер был привязан ко всем адресам, используется константа INADDR_ANY. Если bind вернул не 0, то произошла ошибка. Получаем код ошибки по WSAGetLastError и завершаем программу.

Код ошибки расшифровывается подпрограммой WSA_Err_Decode.

10. Перевод сокета в режим приёма входящих соединений или режим прослушивания (listen). На этом этапе задаётся максимальное число допустимых подключений. Если listen вернул не 0, то произошла ошибка. Получаем код ошибки по WSAGetLastError и завершаем программу.

Код ошибки можно расшифровать подпрограммой WSA_Err_Decode.

11. Далее запускается бесконечный цикл ожидания клиентов. В теле этого цикла присутствует блокирующий метод accept — прокрутка цикла останавливается, пока не приконнектится любой клиент. Этот метод accept возвращает дескриптор сокета, через который можно работать с соединившимся клиентом. Через этот сокет и происходит дальнейший обмен данными с клиентом.

Если наш сервер должен обслуживать несколько клиентов (а мы так и хотели), то в этом месте нужно запустить 2 потока, которые будут работать с сокетом клиента (один на приём, другой на передачу). 2 потока, а не один, нужны потому, что метод recv, который читает данные из сокета, блокирующий (есть и другие варианты, но я их рассматривать не буду, для этого есть спецлитература).

Вот и всё (?) что нужно знать, чтобы написать “всамделишный” сервер.

[Ссылки]

Источник: microsin.net

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru