Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Клиент-серверное приложение, пример приложения, исходник 
V
    Опции темы
Alexey_2007
Дата 30.1.2007, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 30.12.2006

Репутация: нет
Всего: 1



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

Мне нужно именно клиент-серверное приложение, такое чтобы сервер мог получать информацию от несольких клиентов(что очевидно... но у меня что то не получается именно так) TCP\IP.

Если вместе с этим будут каким-либо образом прикручены диалоги - это будет вообще здорово!!!



--------------------
Святая простота
PM MAIL   Вверх
witex
Дата 31.1.2007, 02:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 16.10.2006
Где: Эстония

Репутация: 1
Всего: 4



Здесь! и исходники и маленькое пособие! Только вот ты разделом ошибся! Всё таки сетевое программирование!
--------------------
Я не волшебник, я только учусь."Шлёпни в Гугл" - Афтор Былов Ю.М. 
PM MAIL   Вверх
Alexey_2007
Дата 31.1.2007, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 30.12.2006

Репутация: нет
Всего: 1



thanks!!
--------------------
Святая простота
PM MAIL   Вверх
kleks
Дата 2.5.2007, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 6.10.2005

Репутация: нет
Всего: нет



У меня возник вопрос....по поводу модели "клиент-сервер"....предположим у меня есть сервер и два клиента подключившиеся к этому серверу, как мне организовать банальный чат между этими клиентами??? на примере клиента и сервера описанные по предыдущей ссылке. Т.е. как мне организовать связь между двумя потоками??
PM MAIL   Вверх
-Kp0T-
Дата 2.5.2007, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 23.2.2007

Репутация: 2
Всего: 2



Vivat Крис Касперский, но я тебе не отвечу на вопрос.
Когда знакомился с winsock библиотекой тоже обдумывал реализацию своей задачи в мультипоточности с блокирующими сокетами, но это не лучшее решение, ибо возрастает сложность  программирования.
Более гибкое решение все таки с сокетами, работающими в асинхронном режиме.

Привожу пример эхо-сервера c обоработкой CTRL+BREAK, CTRL+C, VK_RETURN. 
Ну про клиент думаю догадаешься :) ( telnet 127.0.0.1 7777 ).
[ упор на WSAAsyncSelect(), но его использование ведет к увиличению количества потоков на 1 ]

Код

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>

HINSTANCE hInst;
HWND hWnd;

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

char szAppName[]="Example";

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR lpCmdLine,int nCmdShow)
{
    MSG msg;
    WNDCLASSEX    wndclass;

    wndclass.cbSize = sizeof(wndclass);
    wndclass.style    = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance    =    hInstance;
    wndclass.hIcon        =    LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor    =    LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground    =    (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName    =    NULL;
    wndclass.lpszClassName    =    szAppName;
    wndclass.hIconSm    =    LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&wndclass);
    hWnd = CreateWindow(szAppName,"WSAAsyncSelect Example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    if (!hWnd)return FALSE;

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    
    WSADATA       wsd;

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        MessageBox(0, "Can't load WinSock", "Error", 0);
        return 0;
    }

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

    sServerListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (sServerListen == SOCKET_ERROR)
    {
        MessageBox(0, "Can't load WinSock", "Error", 0);
        return 0;
    }

    ULONG ulBlock;
    ulBlock = 1;
    if (ioctlsocket(sServerListen, FIONBIO, &ulBlock) == SOCKET_ERROR)
    {
        return 0;
    }

    localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(7777);

    if (bind(sServerListen, (struct sockaddr *)&localaddr, 
            sizeof(localaddr)) == SOCKET_ERROR)
    {
        MessageBox(0, "Can't bind", "Error", 0);
        return 1;
    }
    
    WSAAsyncSelect(sServerListen, hWnd, WM_USER+1, FD_ACCEPT);
    listen(sServerListen, 4);

    while (GetMessage(&msg, NULL, 0, 0)) 
    {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
    }

    closesocket(sServerListen);
    WSACleanup();
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    SOCKET ClientSocket;
    int ret;
    char szRecvBuff[1024], szSendBuff[1024];
    

    switch (message) 
    {
    case WM_USER+1:
        switch (WSAGETSELECTEVENT(lParam))
        {
        case FD_ACCEPT:
            ClientSocket = accept(wParam, 0, 0);
            WSAAsyncSelect(ClientSocket, hWnd, WM_USER+1, FD_READ | FD_WRITE | FD_CLOSE);
            break;

        case FD_READ:
            ZeroMemory(szRecvBuff,1024);
            ZeroMemory(szSendBuff,1024);
            ret = recv(wParam, szRecvBuff, 1024, 0);
            if (ret == 0)
                break;
            else if (ret == SOCKET_ERROR)
            {
                MessageBox(0, "Recive data filed", "Error", 0);
                break;
            }
            szRecvBuff[ret] = '\0';

            if(szRecvBuff[0]==0x03)closesocket(wParam);
            if(szRecvBuff[0]==0x0D){szRecvBuff[0]='~';szRecvBuff[1]='\0';}

            strncpy(szSendBuff,szRecvBuff,ret);
            szRecvBuff[ret] = '\0';
            ret=send(wParam, szSendBuff,ret, 0);
            break;

        case FD_WRITE://SOCKET READY  to send data
            break;

        case FD_CLOSE:
            closesocket(wParam);
            break;
    }
    case WM_COMMAND:
        wmId    = LOWORD(wParam); 
        wmEvent = HIWORD(wParam); 

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);

        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

PM MAIL   Вверх
kleks
Дата 2.5.2007, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 6.10.2005

Репутация: нет
Всего: нет



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

Код

#include "stdafx.h"
#include <winsock2.h>
#include <iostream>

#pragma comment(lib,"ws2_32.lib")

DWORD WINAPI ConnThread(void* pParam)
{
SOCKET sockClient=(SOCKET)pParam;
SOCKADDR_IN addr;
int length=sizeof(addr);
getpeername(sockClient,(SOCKADDR*)&addr,&length);
printf("Client %s connected\n",inet_ntoa(addr.sin_addr));
char buf[256];
int result=1;
while((result=recv(sockClient,buf,sizeof(buf)-1,0))!=SOCKET_ERROR && result>0)
    {
    buf[result]=0;
    printf(buf);
    printf("\n");
    }
closesocket(sockClient);
printf("Client %s disconnected\n",inet_ntoa(addr.sin_addr));
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////

int main()
{
WORD wVersion;
WSADATA wsaData;
int result;
wVersion=MAKEWORD(1,1);
result=WSAStartup(wVersion,&wsaData);
if (result!=0)
    {
    printf("ERROR: Initialization failed.\n");
    return -1;
    }
SOCKET sockServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (sockServer==INVALID_SOCKET)
    {
    printf("ERROR: Cannot create a socket.\n");
    return -1;
    }
SOCKADDR_IN addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addr.sin_port=htons(1500);
result=bind(sockServer,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
if (result!=0)
    {
    printf("ERROR: Cannot bind socket.\n");
    return -1;
    }
result=listen(sockServer,SOMAXCONN);
if (result!=0)
    {
    printf("ERROR: Cannot connect.\n");
    return -1;
    }
while(1)
    {
    SOCKET sockClient=accept(sockServer,NULL,NULL);
    if (sockClient!=INVALID_SOCKET)
        {
        DWORD dwID;
        HANDLE hThread=CreateThread(NULL,0,ConnThread,(void*)sockClient,0,&dwID);
        CloseHandle(hThread);
        }
    }
return 0;
}
/////////////////////////

PM MAIL   Вверх
-Kp0T-
Дата 4.5.2007, 02:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 23.2.2007

Репутация: 2
Всего: 2



Вообще не зря я тебе привел тут про асинхронные сокеты и WSAAsyncSelect(). Функция действительно мощная. Да ладно.
Как бы я поступил с твоим кодом.
- В пространстве глобальных переменных определил бы стек (как класс).
- Плохо то что поток замерз по функции recv и ждет данные или ошибку :) 
- Тем не менее можно данные о подключений клиентов (в частности нам надо SOCKET) вынести опять таки в globalnamespace или инкапсулировать в класс (как душе угодно)
- Пусть "потоки висят" в ожидании данных, их уже не спасешь. Чтоб срочно отослать данные (которые упали в стек) нужен другой поток (только чтобы отправить второму клиенту).

А теперь собственно программный код, тока на русском языке :)

Поток[i] принял данные по recv, положил в стек данные (что и от кого пришло), отправил сообщение оконной процедуре, [ например, WM_USER+1. Как мы помним, ОСь не использует сообщения выше WM_USER - они зарезервированы для потребителя :) ] и снова поток замерз в ожидании отклика функции recv.

Тем временем, как пришло сообщение WM_USER+1, оконная процедура извлекла данные из стека, решила что и кому слать по полученным данным и создает новый поток (или потоки - сам реши всем слать в одном потоке или в отдельном. - Случай более 2-х клиентов) который займется отправкой данных. После отправки поток должен завершиться с кодом доставки (ошибки).

Я бы тебе код набросал, да сроки поджимать начинают по своему проекту...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0898 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.