![]() |
Клиент-сервер на WinSock
Привет всем юным кодерам! Сегодня я расскажу о написании клиент серверного приложения на winapi библиотеке Winsock.
Как известно клиент-серверное приложение состоит из клиента и сервера. Клиент у нас будет программой визуальной, т.е. это центр управление, с которого мы будет посылать команды не визуальному серверу, который будет из анализировать и выполнять. Что касается компилятора то я буду использовать Borland c++. (Я уже вижу, как в меня летят тухлые помидоры =)). Начнем с простого – клиент. Как ты помнишь это программа визуальная. На главной форме должны присутствовать такие компоненты: Текстовое поле для ввода IP адреса(Edit). Кнопки для подключение и отключения сервера(Button). Кнопки для управлением сервера (Button). (На ваш вкус) http://stranger.nextmail.ru/ex.jpg Да, и не забудь подключить библиотеку: Код:
#includeКод:
{WSAStartUp и создали новый поток, в нем мы уже будет создавать сокет и соединяться с сервером. В первом аргументе функции WSAStartUp мы указали MAKEWORD(1,1) т.е. версия библиотеки 1. Второй аргумент это указатель на структуру WSADATA. В ней будет храниться информация о библиотеки. Итак, поток создан, теперь можно работать с ним. Сначала нужно объявить глобально следующие переменные Код:
SOCKET sClient;А вот и сам поток, что бы программа правильно проинициализировала его, поток нужно добавить до того кода, что я привел выше. Код:
Сначала создаем сокет функцией socket. Первый аргумент это семейство протоколов. Нам нужен TCP, так что указываем AF_INET. Второй аргумент этот спецификация для сокета, т.е. что мы с ним будем делать. Нам нужно установить соединение и передать данные, поэтому указываем SOCK_STREAM. Третий аргумент собственно сам протокол. IPPROTO_TCP соответствуют протоколу TCP. Теперь нам нужно заполнить структуру типа sockaddr_in. В ней храниться информация о созданном сокете. Напомню что переменую (server) данного типа (sockaddr_in) мы объявили глобально. В процессе заполнения структуры нам встречается функция htons. Она осуществляет перевод целого короткого числа из порядка байт, принятого на компьютере, в сетевой порядок байт. Ну и само соединение. Функция connect. Первый параметр это созданный сокет. Второй – указатель на структуру типа sockaddr_in третий размер этой структуры. Если все пройдет успешно, то можно принять данные функцией recv и вывести в текстовое поле. Первый аргумент функции recv это созданный сокет, второй – буфер который мы предварительно создали, третий аргумент это размер буфера (функция strlen возвращает размер строки). И, наконец, последний аргумент это флаги, определяющие метод получения. Они нам не нужны, поэтому указываем 0. В конце кода мы приводим логическую переменную status в значение true. Это нужно чтобы впоследствии избежать ненужного повторного подключения. Кстати, так как мы работаем с классно string в начале файла нужно добавить Код:
#includeДля этого мы напишам функцию GetComand, ее единственным аргументом будет команда которую нужно отправить. Код:
void GetCommand(char* str){ /А далее мы копируем в буфер szMessage значение переменной str. И потом отправляем это значение серверу функцией send; Первый ее аргумент это сокет второй это буфер третий размер буфера. После этого мы получаем ответ функцией recv он аналогична send. После этого выводим ответ в текстовое поле. Ответы мы будем формировать сами при разработке сервера. Замечу, что в коде есть проверка на ошибки. Функция готова к использованию. Например при нажатии на кнопку «Перезагрузка» нужно выполнить такой код: Код:
{Вот мои: «Поменять кнопки мыши» -«AMB» «Блокировать стол» - «BT» «Сообщение» - «MSG» Итак, простейший клиент готов. Подведем итог. Клиент может подключаться к серверу отправлять и принимать команды. Пока это все. Теперь можно приступить к разработке сервера. Как я уже говорил сервер это программа не визуальная. В нем, как и в клиенте нужно загрузить бибилиотеку создать сокет и подключиться. Так же мы встретимся с привязкой к локльному адресу (функция bind) и прослушиванию порта (функция listen). Опять же глобально нужно объявить следущие переменные: Код:
SOCKET sServerListen, sClient;Код:
{Она служит для связи сокета с адресом. Т.е. первым аргументом мы передали сокет, вторым указатель на структуру с адресом, третим – размер структуры. Теперь сокет готов к работе и можно прослушивать порт на соеденение со стороны клиента. Функция listen. У нее два параметра. Сокет и кол-во клиентов которые могут подключиться к серверу. Т.к. сервер должен постоянно находиться в памяти и принимать соеденения, то мы запускаем бесконечный цикл. Функция accert проверяет подключающийся клиент и разрешает соеденения. Первый параметр это сокет. Второйуказатель на структуру типа sockaddr ну и третий размер структуры. sClient будет указателем на новый сокет. После этого создаем новый поток для обмена данными. Вот этот поток: Код:
DWORD WINAPI ClientThread(LPVOID lpParam)Надеюсь, смысл команд понятен. Замечу, что после выполнения каждой команды мы посылаем клиенту уведомление об успешности выполнения. Например, вот участок кода: Код:
if(a=="BT")Все мы подготовили простейший макет клиент – сервера и даже внедрили некоторые функции. Чтое еще можно зделать? Все информация которую мы передаем в winsock передаеться байтами поэтому можно передать любой файл. Например скриншот экрана. Если подумать, то можно организовать даже потоковое видео. Вот примерный алгоритм на стороне сервера храним текущий кадр и прошлый, сверяем разницу между ними, получаем битовую маску, она сжимается нефигово, потом передаем изменившиеся части(только их, сплошным потоком) клиент уже смотря по маске подставляет эти части в нужные места Правда программно я это не проверял. Может ты зделаешь? Это все. До свидания. ps в приведенных кодах есть несколько ошибок с точки зрения программирование, которые я так и не удосужился исправить ©StraNger |
Да вообщем то ничего нового. Просто пересказ того, чего уже итак полно в инете.
|
| Время: 21:38 |