Нажмите CTRL-D чтобы добавить нас в закладки
Внимание! Вы находитесь в незащищенном режиме (HTTP). Для перехода в защищенный режим SSL, нажмите здесь
HackZone.RU - Клиент сервер на основе WinSock Актуальные базы 2GIS в форматах CSV,Excel,SQL
Войти / Регистрация / Участники
Определение даты выпуска iPhone по серийному номеру
-
Поиск по сайту
Форумы



Реклама

Поиск ТОП Добавить публикацию

Клиент сервер на основе WinSock

27.03.2009

Привет всем юным кодерам! Сегодня я расскажу о написании клиент серверного приложения на winapi библиотеке Winsock.

Как известно клиент-серверное приложение состоит из клиента и сервера. Клиент у нас будет программой визуальной, т.е. это з центр управление, с которого мы будет посылать команды не визуальному сервервестноу, который будет их анализировать и выполнять.
Что касается компилятора то я буду использовать Borland c++. (Я уже вижу, как в меня летят тухлые помидоры =)).
Начнем с простого – клиент.
Как ты помнишь это программа визуальная. На главной форме должны присутствовать такие компоненты:
Текстовое поле для ввода IP адреса(Edit).
Кнопки для подключение и отключения сервера(Button).
Кнопки для управлением сервера (Button). (На ваш вкус)



Да, и не забудь подключить библиотеку:

#include

Первое что бы сделаем это подключение к серверу.

{
WSADATA wsd;
If (WSAStartup(MAKEWORD(1,1), &wsd) != 0) // загрузка библиотеки и проверка на //ошибки
{
// если ошибки есть, то проинформировать юзера
Form1->Memo1->Lines->Add("Error load WinSock");
return ;
}
// создание нового потока
HANDLE hThread;
DWORD idThread;
hThread = CreateThread(NULL, 0, Thread, 0, 0, & idThread);
}

Что тут происходит? Да пока ничего. Мы просто загрузили библиотеке функцией WSAStartUp и создали новый поток, в нем мы уже будет создавать сокет и соединяться с сервером. В первом аргументе функции WSAStartUp мы указали MAKEWORD(1,1) т.е. версия библиотеки 1. Второй аргумент это указатель на структуру WSADATA. В ней будет храниться информация о библиотеки.

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

SOCKET sClient;
int ret, i;
struct sockaddr_in server;
struct hostent *host = NULL;
bool status;
 
По ходу дела мы разберемся, что к чему.
А вот и сам поток, что бы программа правильно проинициализировала его, поток нужно добавить до того кода, что я привел выше.


DWORD WINAPI Thread(LPVOID lpParam)
{

char* szServerName= new char;
szServerName="12345";
szServerName=strcpy(szServerName,(Form1->Edit1->Text.c_str()));

//создание сокета
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
MessageBox(0, "Can't create socket", "Error", 0);
return 1;
}
//заполненеие структуры sockaddr_in
server.sin_family = AF_INET;
server.sin_port = htons(7070);
server.sin_addr.s_addr = inet_addr(szServerName);

//само соеденение

if (connect(sClient, (struct sockaddr *)&server,
sizeof(server)) == SOCKET_ERROR)
{

Form1->Memo1->Lines->Add("connect failed");
return 1;
}
char szRecvBuff[1024];
//принимаем данные
ret = recv(sClient, szRecvBuff, strlen(szRecvBuff), 0);
if (ret == SOCKET_ERROR)
{

Form1->Memo1->Lines->Add("recv failed");
}
// выводим данные
String q=szRecvBuff;
Form1->Memo1->Lines->Add(q);
status=true;

}

Перед основным кодом мы заносим в переменную szServerName значение текстового поля, в который пользователь введет ip адрес.
Сначала создаем сокет функцией 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){ /
//если мы подлючены то…
if(status==true)
{
char* szMessage= new char;
szMessage="0000";
// копируем в буферв вписаную нами команду
strcpy(szMessage, str);
// отправка команды
ret = send(sClient, szMessage, strlen(szMessage), 0);
if (ret == SOCKET_ERROR)
{
} Form1->Memo1->Lines->Add("send failed");


//получение ответа
char szRecvBuff[1024];
ret = recv(sClient, szRecvBuff, 1024, 0);
if (ret == SOCKET_ERROR)
{

Form1->Memo1->Lines->Add("recv failed");
}
String q=szRecvBuff;
//вывод ответа
Form1->Memo1->Lines->Add(q);
}
else
{
//если мы не подключены то осведомить пользователя
Form1->Memo1->Lines->Add("The server is not connected");
 
}
}

Сначала происходит проверка переменной status. Если она равна true то мы подключены и можно выполнять дальнейший код.
А далее мы копируем в буфер szMessage значение переменной str.
И потом отправляем это значение серверу функцией send;
Первый ее аргумент это сокет второй это буфер третий размер буфера.
После этого мы получаем ответ функцией recv он аналогична send.
После этого выводим ответ в текстовое поле.
Ответы мы будем формировать сами при разработке сервера.
Замечу, что в коде есть проверка на ошибки.
Функция готова к использованию.
Например при нажатии на кнопку «Перезагрузка» нужно выполнить такой код:

{
GetCommand("RB");
}

Кстати смотри не запутайся в командах т.к. в сервера из нужно будет анализировать.
Вот мои:
«Поменять кнопки мыши» -«AMB»
«Блокировать стол» - «BT»
«Сообщение» - «MSG»
Итак, простейший клиент готов. Подведем итог.
Клиент может подключаться к серверу отправлять и принимать команды. Пока это все.

Теперь можно приступить к разработке сервера.
Как я уже говорил сервер это программа не визуальная.
В нем, как и в клиенте нужно загрузить бибилиотеку создать сокет и подключиться.
Так же мы встретимся с привязкой к локльному адресу (функция bind) и прослушиванию порта (функция listen).
Опять же глобально нужно объявить следущие переменные:

SOCKET sServerListen, sClient;
struct sockaddr_in localaddr,
clientaddr;
HANDLE hThread;
DWORD dwThreadId;
int iSize;
WSADATA wsaData;
 

Итак начнем вот код главной функции:

{
//загрузка библиотеки
WSAStartup(MAKEWORD(1, 1), &wsaData);
Создание сокета
sServerListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
заполнение струтуры адреса
localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(7070);
//привязка адреса к сокету
bind(sServerListen, (struct sockaddr *)&localaddr,sizeof(localaddr));
//простушиваниче порта
listen(sServerListen, 2);
while (1)
{
iSize = sizeof(clientaddr);
//разрешение на соеденение
sClient = accept(sServerListen, (struct sockaddr *)&clientaddr,&iSize);
//создание потока для приема и отправки данных
hThread = CreateThread(NULL, 0, ClientThread,(LPVOID)sClient, 0, &dwThreadId);
CloseHandle(hThread);
}
closesocket(sServerListen);
return 0;
}

До заполнения структуры адреса все идет так же. После этого вызываеться функция bind.
Она служит для связи сокета с адресом.
Т.е. первым аргументом мы передали сокет, вторым указатель на структуру с адресом, третим – размер структуры.
Теперь сокет готов к работе и можно прослушивать порт на соеденение со стороны клиента.
Функция listen. У нее два параметра. Сокет и кол-во клиентов которые могут подключиться к серверу. Т.к. сервер должен постоянно находиться в памяти и принимать соеденения, то мы запускаем бесконечный цикл.
Функция accert проверяет подключающийся клиент и разрешает соеденения.
Первый параметр это сокет. Второйуказатель на структуру типа sockaddr ну и третий размер структуры. sClient будет указателем на новый сокет.
После этого создаем новый поток для обмена данными.
Вот этот поток:


DWORD WINAPI ClientThread(LPVOID lpParam)
{

SOCKET sock=(SOCKET)lpParam;


string a="";
char szRecvBuff[1024],szSendBuff[1024] ;
int ret;
strcpy(szSendBuff,"Server connect!");
send(sock, szSendBuff, sizeof(szSendBuff), 0);


while(1)
{
//Получаем данные
ret = recv(sock, szRecvBuff, 1024, 0);

if (ret == 0)
break;
else if (ret == SOCKET_ERROR)
{
MessageBox(0, "Recive data filed", "Error", 0);
break;
}
szRecvBuff[ret] = '\0';
//записываем в стринговую переменную для дальнейшей обработки
a=szRecvBuff;
//Проверка команд
//если команда перезагрузки то…
if(a=="RB")
{
ExitWindowsEx(EWX_REBOOT, 0);
strcpy(szSendBuff,"Computer reboot =) ");
send(sock, szSendBuff, sizeof(szSendBuff), 0);

}
else
//если команда поменять кнопки мышки то…
if(a=="AMB")
{

SwapMouseButton(false);

strcpy(szSendBuff,"The buttons on the mouse were displaced");
send(sock, szSendBuff, sizeof(szSendBuff), 0);
}
Else
//если команда для вывода сообщения то…
if(a=="MSG")
{
MessageBox(0, " It is time to you to be hung up", "Error", 0);
strcpy(szSendBuff," The message is sent");
send(sock, szSendBuff, sizeof(szSendBuff), 0);

}
Else
//если команда для блокирования стола
if(a=="BT")
{
HWND h=GetDesktopWindow();
EnableWindow(h, FALSE);
strcpy(szSendBuff,"The working table is blocked");
send(sock, szSendBuff, sizeof(szSendBuff), 0);

}
 

}

Сначала мы передаем клиенту сообщение о том, что сервер успешно подключен и готов к работе. Далее мы получаем команды и записываем полученную команду в стринговую переменную (не забудь добавить #include ) для того, что бы дальше ее проанализировать. Команд у нас не много поэтому здесь происходит проверка условием.
Надеюсь, смысл команд понятен. Замечу, что после выполнения каждой команды мы посылаем клиенту уведомление об успешности выполнения. Например, вот участок кода:

if(a=="BT")
{
HWND h=GetDesktopWindow();
EnableWindow(h, FALSE);
strcpy(szSendBuff,"The working table is blocked");
send(sock, szSendBuff, sizeof(szSendBuff), 0);

}

После того как стол заблокирован мы отправляем клиенту сообщение ,"The working table is blocked" – что означает рабочий стол заблокирован.
Все мы подготовили простейший макет клиент – сервера и даже внедрили некоторые функции. Чтое еще можно зделать? Все информация которую мы передаем в winsock передаеться байтами поэтому можно передать любой файл. Например скриншот экрана.
Если подумать, то можно организовать даже потоковое видео. Вот примерный алгоритм

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

При копировании материалов ссылка на HackZone.RU обязательна

Добавить страницу в закладки

 Детали
Категория: Программирование
Опубликовал: -StraNger-
Просмотров: 14134
Проголосовало через SMS: 0
  Разместить у себя на сайте
Прямая ссылка
HTML
BBCode ссылка
BBCode ссылка с текстом

 Комментарии (оставить свой комментарий можно здесь)
При все уважении к Тебе - если ты выделяешь память в С++: char* szMessage= new char; , то не забудь её освободить - это тебе не Java или C# со своими сборщиками мусора Wink
(Включи в проекте слежение за динамической памятью [CodeGuard] - все сам увидишь)
28.03.2009 / Nitrogen_x
неплохая тема..Thumbsup тока объясни маладому(мне) куда применяеться этот алгоритм программы ,чтобы я, грубо-говоря,взял и применил твое замечательное детище в дело..)) (по голове сильно не пинайте,объяснил как мог,..маладой...)
04.04.2009 / shtabs
Только зарегистрированные пользователи могут оставлять комментарии

Зарегистрироваться *** Авторизоваться


 Последние новости и статьи  Последние сообщения с форумов
  • Самозащита от вируса Petya
  • Google Pixel взломали за 60 секунд
  • В CMS Joomla обнаружена критическая 0-day уязвимость
  • ФБР не смогло взломать протокол шифрования переписки террористов ...
  • Полиция обыскала дом предполагаемого создателя платежной системы ...
  • Google: квантовый ПК будет в 100 млн раз быстрее стандартных чипо...
  • "Лаборатория Касперского" констатирует усиление атак кибергруппир...
  • Microsoft Edge откроет исходные коды ChakraCore
  • Anonymous объявили 11 декабря «днём троллинга» ИГИЛ
  • Миллионы телевизоров, смартфонов и маршрутизаторов оказались уязв...

    Все новости... Все статьи... Прислать новость RSS
  • Взлом и безопасность / Новичкам » Взлом Whatsapp.Viber.Instagram. facebook.Узнаем взломаем !!!
  • Взлом и безопасность / Новичкам » Профессиональные услуги по взлому
  • Разное / Продам, отдам » Re: Продам базы 2ГИС (2gis) в форматах CSV, Excel, SQL
  • Взлом и безопасность / Новичкам » Зачем используют чужие имеил адреса для подписки?
  • Взлом и безопасность / Программы » Взлом программы
  • Взлом и безопасность / Программы » Re: Viber перехват сообщений.
  • Разное / Ищу работу » Re: Качественный подбор паролей к почтам.
  • Разное / Ищу работу » Re: -=Мощный DDoS service/ДДоС сервис=-
  • Взлом и безопасность / WEB сайтов » Ищу единомышленников
  • Разное / Продам, отдам » Re: Продам базы 2ГИС (2gis) в форматах CSV, Excel, SQL

    Все форумы... RSS


  • Разместить рекламу
    © HackZone Ltd. 2007-2012. Все права зарегистрированы.
    Перепечатка материалов без согласования и указания источника будет преследоваться по Закону

    О проекте | История проекта | Размещение рекламы | Обратная связь | Правила поведения на портале
    Ya-Cyt службы мониторинга серверов

    #{title}

    #{text}

    x

    #{title}

    #{text}