Если вы читали блог, то наверняка заметили, что на его страницах есть целый цикл статей по взаимодействию winsock и C++. Сегодня я решил написать заметку о архитектуре клиент — сервер. Я постараюсь реализовать два приложения на C++: клиент, который будет посылать пакет «запрос» и затем сразу же принимать «ответ», и сервер, который будет работать в многопоточном режиме (каждому клиенту — свой поток) и к идентификатору каждого пакета «запрос» прибавлять единицу и посылать обратно. Писать естественно буду на VC 6.0, исходники будут прилагатся.

jw 1019 jxta1 e1342261532324 Архитектура клиент сервер

Ну что же, вводная часть окончена, приступаем к реализации…

Для того, чтобы вам было более понятно я сначала опишу структуру — пакет:

typedef struct _TEchoStruct
{
        DWORD dwId;
        char szContent[256];
}TEchoStruct;

Данная структура будет включена в исходные коды как клиента так и сервера. Поле dwId является идентификатором пакета. Именно оно будет инкреминироватся на стороне сервера и отправлятся обратно. Поле szContent является содержанием пакета. Оно не будет изменятся, и будет служить для подтверждения корректности пакета. И сервер и клиент разумеется будут работать на одном и том же порту:

#define port 93

Также, так как пример наш является просто примером я позволю себе в клиенте жестко прописать ip сервера:

#define serv "127.0.0.1"

Теперь, когда вся подготовка окончена рассмотрим код сервера.

int main()
{
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);

        SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

        SOCKADDR_IN ssin = {0};
        ssin.sin_family = AF_INET;
        ssin.sin_addr.s_addr = INADDR_ANY;
        ssin.sin_port = htons(port);

        bind(s,(SOCKADDR *)&ssin,sizeof(ssin));
        listen(s,SOMAXCONN);

        while(1)
        {
                SOCKADDR_IN csin = {0};
                int csin_size = sizeof(csin);
                SOCKET c = accept(s,(SOCKADDR *)&csin,&csin_size);

                printf("New thread: connect from %s\n",inet_ntoa(csin.sin_addr));

                DWORD dwId;
                HANDLE hThread = CreateThread(NULL,0,ClientThread,(LPVOID)c,0,&dwId);
                CloseHandle(hThread);
        }

        closesocket(s);

        WSACleanup();
        return 0;
}

Начало кода, если вы разумеется читали предыдущий цикл статей по winsock, должно быть знакомо. Инициализуем winsock, создаем сокет, дальше объявляем и инициализируем структуру SOCKADDR_IN. Для того, чтобы можно было соединятся с любого IP пишем:

ssin.sin_addr.s_addr = INADDR_ANY;

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

DWORD WINAPI ClientThread(LPVOID p)
{
        SOCKET c = (SOCKET)p;

        TEchoStruct es = {0};

        recv(c,(char *)&es,sizeof(TEchoStruct),0);

        printf("Packet ID: %d\tPacket Content: %s\n",es.dwId,es.szContent);

        es.dwId ++;

        send(c,(char *)&es,sizeof(TEchoStruct),0);

        closesocket(c);
        ExitThread(0);
        return 0;
}

Здесь тоже все предельно понятно: получаем сокет из переданного параметра, получаем из него структуру TEchoStruct, выводим, инкриминируем и отправляем обратно. Потом закрываем сокет клиента и выходим из потока. Все, с сервером вроде бы разобрались, перейдем к клиенту.
Клиент имеет следующий код:

int main()
{
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);

        SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

        SOCKADDR_IN ssin = {0};
        ssin.sin_family = AF_INET;
        ssin.sin_addr.s_addr = inet_addr(serv);
        ssin.sin_port = htons(port);

        connect(s,(SOCKADDR *)&ssin,sizeof(ssin));

        printf("Connecting to %s:%d\n",serv,port);

        TEchoStruct es = {0};

        printf("Enter id packet: ");
        scanf("%d",&(es.dwId));
        fflush(stdin);
        printf("Enter content packet: ");
        gets(es.szContent);

        send(s,(char *)&es,sizeof(TEchoStruct),0);

        printf("Send ->\nPacket ID: %d\tPacket Content: %s\n",es.dwId,es.szContent);

        memset((char *)&es,0,sizeof(TEchoStruct));
        recv(s,(char *)&es,sizeof(TEchoStruct),0);

        printf("Recv 
                      

Здесь опять же все банально и до функции connect идет шаблон. После же мы объявляем и инициализируем нашу структуру, отправляем ее и выводим что она отправлена, затем обнуляем ее, и получаем туда же. После чего опять выводим. Вот вроде бы и все. Как и обещал, далее прилагаю исходники: client_server.

tt twitter big4 Архитектура клиент сервер tt digg big4 Архитектура клиент сервер tt facebook big4 Архитектура клиент сервер tt gmail big4 Архитектура клиент сервер tt myspace big4 Архитектура клиент сервер tt reddit big4 Архитектура клиент сервер

Оставить комментарий

CAPTCHA изображение
Обновить изображение
*

RSS-подписка NIG Twitter-подписка NIG

Метки
Друзья
Блог линуксоида Программы для диагностики компьютера
Супер Pixel
Убивалка флешаБэкконект шелл. Часть вторая.Бэкконект шелл. Начало.НАМ для деления чиселПростая арифметикаПередача файлов. Часть третья. Клиент.Dll injectionСканер портовКодировка текста в BMPРухнул на два дняПередача файлов. Часть вторая. Сервер.Поворот и BMPCRC32 суммаBMP форматфайловые вирусыассемблер, строкиАссемблер и матрицапримеры ассемблерМногопоточное программированиеАрхитектура клиент — серверРаздача ICQПишем шуткупишем паукаПривет от ДжеймсаОбход firewallЗагрузка картинок на Gyazo, прямо из ThunarКейлоггер 3Плюшки в контекстном меню Thunarc по сетиКейлоггер 2КейлоггерСкачать Ассемблер!VirusCheckerОтморозки мешают жить ?! Не проблемма !Cкрипты для взлома аккаунтов QIPWinAPI. Работа с файлами. Часть третья. ЧтениеDlink exploitБрут сайта etxt.ruКрасивая раскладка клавиатуры в GnomeМои безделушки на PerlКак запускать Perl скрипты под WindowsБрутфорс партнёрки ZipCoinПарсер upwap.ruИзменения в блогеЧудо ЗаливалкаСкрипт для загрузки файлов на Zalil.ruЯндекс «чоткий» поисковик!WinAPI. Работа с файлами. Часть вторая. ЗаписьWinAPI. Работа с файлами. Часть первая. ПоискПолучение MD5 хеша средствами C++Что нам стоить letitfile.com забрутить?WarCraft III запуск под LinuxЭнтропия файлаWinsock и C++. Мини прокси. Часть |\\/. Завершающая.Перепилил чекер для 4gameЧекер акаунтов YoupornCMailSend v 1.1. Отправка почы без проблемСлучайные числаWinsock и C++. Часть |||. smtp монстр.Брутфорс LetitFile.comИспользование X-Forwarded-For, для обмана веб-сервера, подмена IP подручными средствамиДело было вечером, делать было нечего…Мысли о аудио сервереПарсер ников из твиттераКонец школоло…Perl+Linux. Заметка первая (Удобный Paste bin).Бэкконект шелл.E-MAIL + winsocket + Cpp. Сложно?winsock и C++. Часть ||. Атака клоунов.C++ резолвинг адресаPerl, анализ HTML кода и определение CMSМатематика в C++winsock и C++