Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Flash Приложения: AIR, Zinc и тд. (http://www.flasher.ru/forum/forumdisplay.php?f=94)
-   -   Сервер для Flash на C++ (socket) (http://www.flasher.ru/forum/showthread.php?t=134415)

deman455 29.12.2009 17:52

Сервер для Flash на C++ (socket)
 
Как на с++ сделать сервер, документации, или чтото. И как его седенить?
Да я порылся в интренете нашол кучу всякого, вот к примеру server Ruby:
http://haxe.ru/node/134 никогда не слышал об таком языке программирования:D
Начитался что после С++ надо какуюто платформу что такое платформа ?
Нашол какуюто ссылку плотформу ACE .
Та даже самый просто php чат как сделать? у меня есть прекрасный исходник пхп чата флеш+пхп , я взял шаровый пхп хостинг, ну и всеровно, чат никак не могу запустить.
Дальше:
Простейшая передача числа из клиента к серверу (тоесть у примеру с сайта на сервер у меня на компьютере ip: port). Как такое сделать? как сделать чтобы к примеру записалось число в xml файл и это число сразу отобразилось у другой флешки.

Короче словом, как сделать сервер для потокового приема и отдачи хотябы чисел. Можно самый примитивный, или исходник какойто. Помогите розобратся в этой мурне )

alexcon314 29.12.2009 18:10

От всей души вкладываю примитивный исходник, рабочий, проверял в связке с флэшем:
Код:

#include <iostream>
using namespace std;
#include <winsock2.h>

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

void main(void) {
        char PCName [30], ClientName[30], Message[200];
        WSAData WSADat; // Свойства WinSock (результат функции WSAStartup)
        sockaddr_in sin; // Свойства(адрес) создаваемого сокета
        SOCKET Sock, Client; // Серверный и клиентский сокеты

        WSAStartup(0x0202,&WSADat); // Инициализация WinSock
                                                                // 0x0202 - версия WinSock. Может быть 1.0, 1.1, 2.0, 2.2
                                                                // WSADat - структура, куда будут занесены рез. инициализации
        gethostname(PCName, 30); // Получение имени текущего ПК

        sin.sin_family = AF_INET; // Тип адреса
        sin.sin_addr.s_addr = 0;  // IP-адрес сервера (пори создании сервера можно 0)
        sin.sin_port = htons(2803); // Номер порта сервера
        Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Создание сокета
        bind(Sock, (sockaddr*)&sin, sizeof(sin)); // Связывание созданного сокета с адресом sin

        // ***** Ожиданеи клиента
        cout << "Wait of client..." << endl;
       
        listen(Sock, SOMAXCONN); // Прослушивание сокета сервером (для подключения клиента)
        Client = accept(Sock, (sockaddr*)&sin, 0); // Ожидание клиента
        recv(Client, ClientName, 30, 0); // Получение имени компьютера клиента
        send(Client, PCName, strlen(PCName) + 1, 0); // Отправка имени этого компьютера (сервера)

        cout << "Client ( " << ClientName << " ) has connected!" << endl;

        // ***** Меню
        int Menu;
        do {
                cout << "1. Send message;" << endl;
                cout << "2. Get Message;" << endl;
                cout << "3. Quit;" << endl;

                cout << "Make your selection: ";        cin >> Menu;

                switch (Menu) {
                case 1:
                        // Отправка сообщения клиенту
                        cout << "Enter message: "; cin.get();
                        cin.getline(Message, 200);
                        if (send(Client, Message, strlen(Message) + 1, 0) != SOCKET_ERROR) cout << "Sent!\n";
                        else cout << "Error of sending!\n";
                break;
                case 2:
                        // Приём сообщения от клиента
                        if (recv(Client, Message, 200, 0) != SOCKET_ERROR) {
                                cout << Message << endl;
                                cin.get();
                        }
                        else cout << "Error of getting!\n";
                break;
                };

                cout << endl;
        } while (Menu != 3);

        // Закрытие сокетов и окончание работы с WinSock
        closesocket(Sock);
        closesocket(Client);
        WSACleanup();
}

Компилил под MS VS C++ 2005 Express. Полегчало? :D.
Да, хорошо бы подковаться малость, а то опять тема получится никакая.

deman455 29.12.2009 19:00

alexcon314
Полегчало =)
но ещё интересует как подконектить к нему флешку ???

alexcon314 30.12.2009 09:19

Ну, как подконнектить... так вот, примерно:
Код:

// AS 2.0 socket client code
var socket:XMLSocket = new XMLSocket();
socket.onConnect = function(success:Boolean) {
        if (success) {
                o("Connection succeeded!");
                socket.send("ogogo");
        } else {
                o("Connection failed!");
        }
};
if (!socket.connect("127.0.0.1", 2803)) {
        o("Connection failed!");
}
socket.onClose = function(){
        o("Connection closed.");
}
socket.onData = function(src) {
        o(src);
};
sendBtn.onRelease = function() {
        socket.send(toSend.text);
};
function o(msg) {
        out.text = msg + newline + out.text;
}

В AS 3.0 можно юзать класс Socket.

stinkybob 15.01.2010 17:47

Спасибо все классно все работает только есть 2 вопроса

1) при компиляции в swf и при запуске этого swf плеер сообщает что производится попытка небезпасной операции (как это убрать чтобы не у меня ни у остальных клиентов этой ошибки не было)

2) Сокет позволяет только 1 соединение? просто если запускать 2 клиента то 1 не работает, или это зависит от самого сокет сервера? =)


Заранее спс за ответы

alexcon314 15.01.2010 18:15

1. Это нормально. Так работает система безопасности плеера. Разберитесь с ней.
2. Исходник примитивный. Это просто иллюстрация, демонстрирующая некоторые базовые принципы.
Если хочется что-то получше, ну... я не знаю. В сети полно исходников и компонент для сборки сервера. Вы сделали первый шаг, так не останавливайтесь.

stinkybob 15.01.2010 18:20

ММ а подскажите пожалуйста каким образом с ней можно разобраться =) и так чтоб не только у себя =) и кстати ошибку такую выдает только если свфку запускаешь а когда на веб сервер выкладываешь так сразу коннект еррор но ошибки той нету

alexcon314 15.01.2010 18:31

Если запускаете свф локально, в настройках публикации (File -> Publish Settings...)на вкладке Flash выберите Access network only.

stinkybob 15.01.2010 22:29

Сижу весь день ломаю голову как сделать "многопользовательский сервер" ничего пока не вышло :(

Я еще вычитал что надо делать 2 сокетами 1 соединяет 2 меняет данные

Если не сложно может накините какой-нибудь примерчик

И вобще как образом осуществить весь процесс этого онлайна, где копать, что необходимо.

Цель у меня такая:

-Есть база Mysql в ней допустим [login, pass, lvl, exp, hp]
-Есть сайт PHP в нем все бонально просто [авторизация, после логина доступ к игре, от туда мы выхвавтыаем $_SESSION['login'] пихаем во flash дальше из Flash'a посылаем запрос на сокет сервер [login] ]
-Сокет сервер [берет этот [login] и на основании его делает запрос в базу откуда выхватывает всю строку и посылает обратно ]
-Flash уже действует дальше на основании этих данных

Вроде все понятно (сама структура) поправьте меня если все происходит не так

Половиу из этого я знаю как реализовать половину нет

-Каким образом принятые данные из сокет сервера можно преобразовать в переменные и чтобы во флеше все выстроилось как надо
-Как сделат так чтобы при обращении к сокет серверу происходило какбы потоковое действие и не надо было ждать пока 1 пользователь закончит общаться с сокетами

-и вот самого главного я не пойму каким эт образом можно различить юзеров, да даже бонально крестики нолики как свф поймет когда ходит юзер1 а когда юзер2 =)

БОЛЬШАЯ просьба если кому не трудно, кто сталкивался или просто знает, дайте плз совет, ссылку, пример, все что угодно!

Огромный поклон, Спасибо!

alexcon314 16.01.2010 01:28

Ну вот, еще один примитивный исходник:
Код:

#include <iostream>
#include <process.h>
#include <windows.h>
#include <conio.h>
using namespace std;
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "mswsock.lib")

unsigned int _stdcall client_thread(void *client_soket)
{
        char Message[200];
        SOCKET Client = (SOCKET)client_soket;
        int len = 0;
        do {
                // Приём сообщения от клиента
                len = recv(Client, Message, 200, 0);

                // Обработка сообщения
                // Если ошибка, выходим из цикла ожидания.
                if(len == SOCKET_ERROR) break;
               
                // Если длина сообщения 0, значит клиент закрыл свой сокет.
                if(len == 0){
                        cout << "Client socket closed." << endl;
                        break;
                }
                cout << Message << " ";

                // Отправка сообщения клиенту (эхо)
                len = send(Client, Message, strlen(Message) + 1, 0);
                // Если ошибка, выходим из цикла ожидания.
                if(len == SOCKET_ERROR)  break;
                cout << " (echo sent)" << endl;

        } while (1);

        closesocket(Client);
        _endthreadex(0);
        return 0;
}

void main(void) {
        char                        hname [64];                        // Имя хоста
        WSAData                        WSADat;                                // Свойства WinSock (результат функции WSAStartup)
        sockaddr_in                server_sin;                        // Свойства(адрес) создаваемого сокета сервера
        sockaddr_in                client_sin;                        // Свойства(адрес) создаваемого сокета сервера
        SOCKET                        Client, Sock;                // Серверный и клиентский сокеты
        WORD                        wVersionRequested;        // Версия WinSock
        int                                res;
        HANDLE                        hThread;
        // Инициализация WinSock 0x0202. Может быть 1.0, 1.1, 2.0, 2.2
        wVersionRequested = MAKEWORD( 2, 2 );
        // WSADat - структура, куда будут занесены результаты инициализации
        if(WSAStartup(wVersionRequested, &WSADat))       
                {cout << "Winsock can't be initialized. Press any key to exit...";        _getch(); return;}
        // Получение имени текущего ПК
        if(gethostname(hname, 64) == SOCKET_ERROR)       
                {cout << "Not host name. Press any key to exit...";        _getch(); return;}
       
        memset (&server_sin, 0, sizeof(server_sin));
        server_sin.sin_family                = AF_INET;        // Тип адреса
        server_sin.sin_addr.s_addr = htonl(INADDR_ANY);        // IP-адрес сервера, здесь 0, можно так: inet_addr("127.0.0.1")
        server_sin.sin_port                = htons(2803);        // Номер порта сервера

        // Создание сокета
        Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (Sock == INVALID_SOCKET)       
                {cout << "Error create socket. Press any key to exit...";        _getch(); return;}

        // Связывание созданного сокета с адресом sin
        res = bind(Sock, (sockaddr*)&server_sin, sizeof(server_sin));
        if (res == SOCKET_ERROR)
                {cout << "Error bind socket. Press any key to exit...";        _getch(); return;}

        // Прослушивание сокета сервером (для подключения клиента)
        res = listen(Sock, SOMAXCONN);                       
        if(res == SOCKET_ERROR)
                {cout << "Error listen socket. Press any key to exit...";        _getch(); return;}
        // Ожидание клиента
        hThread = NULL;
        while(1)
        {
                cout << "Wait of client..." << endl;
                // Стартуем поток обработки клента, если таковой был создан после accept
                if(hThread)
                {
                        ResumeThread(hThread);
                        CloseHandle(hThread);
                        hThread = NULL;
                }
                // Если дождались очередного клиента, делаем аccept
                int sin_len = sizeof(client_sin);
                memset (&server_sin, 0, sin_len);
                Client = accept(Sock, (sockaddr*)&client_sin, &sin_len);       
                if(Client == INVALID_SOCKET)
                        {cout << "Error accept client. Press any key to exit...";        _getch(); break;}

                // Пытаемся получить имя хоста клиента, его ip и порт
                      HOSTENT *hst;
                      hst = gethostbyaddr((char *)&client_sin. sin_addr.s_addr, 4, AF_INET);
                char port[6] = "";
                _itoa_s(client_sin.sin_port,port,6,10);
                      // Вывод сведений о клиенте
                printf("New client  %s [%s:%s] has connected!\n", (hst) ? hst->h_name : "", inet_ntoa(client_sin.sin_addr),port);

                // Отправка имени этого компьютера (сервера)
                res = send(Client, hname, strlen(hname)+1, 0);
                if(res == SOCKET_ERROR)
                        {cout << "Error send. Press any key to exit...";        _getch(); break;}

                cout << " Start client thread...";
               
                // Создаем поток обработки сообщений клиента, стартуем его чуть позже в случае успеха
                hThread = (HANDLE)_beginthreadex(NULL, 0, client_thread, (void*)Client, CREATE_SUSPENDED, NULL);
                if(!hThread)
                        {cout << "Error start client thread. Press any key to exit...";        _getch(); break;}

                cout << " ok." << endl;
        }
        CloseHandle(hThread);
        closesocket(Sock);
        WSACleanup();
}

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

Каким образом принятые данные из сокет сервера можно преобразовать в переменные и чтобы во флеше все выстроилось как надо
А вот это уже зависит только от того, как вы сами захотите передавать данные: это может быть строка с разделителями, xml или просто любая последовательность байтов.
Цитата:

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

UPD:
немного причесал исходник.
это читать для дальнейшего понимания, что есть непримитивный исходник.


Часовой пояс GMT +4, время: 15:24.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.