Полезное

Мы Вконтакте

Discord канал

#
Аватара пользователя
Пользователь
Сообщения: 32
MHard писал(а):
видео? улыбнуло.
пару видео о программировании сети на с++ со своей структурой пакетов для выделенного сервера, это сильно.

не обязательно кстати использовать boost asio и прочие фреймворки, можно и свое сделать.

Показать основы и принципы построения именно ммо модели не так уж и сложно а дальше кто на что горазд, вопрос ведь был в том что человек не понимает как делать
Аватара пользователя
Пользователь
Сообщения: 2
MHard писал(а):
я свою сеть делал (сервер и блок для UE) на winsock2.h.
в типовых механизмах встроенных в UE даже не пытался разбираться т.к. мне UE нужен для применения в MMO, а тут типовые механизмы бессильны.

если смогу чем то помочь по написанию своей сети то спашивайте.


редактор физики на авторитарном сервере какой использовали или все сами ручками писали?
winsock это же подключаемая библиотека к чему подключали?

Народ, может снизойдете до начального уровня и объясните по пунктам что и как. Ведь не у всех вся жопа в мозолях от программирования. Ведь порой просто можно же задать направление.

К примеру используемый компилятор для написания серверной части "Clang" - ссылка на сайт его http://clang.llvm.org/

Понятие авторитарного сервера в картинках http://pt.slideshare.net/flashgamm/dev-gamm5-1
Аватара пользователя
Пользователь
Сообщения: 1
MHard писал(а):
я свою сеть делал (сервер и блок для UE) на winsock2.h.
в типовых механизмах встроенных в UE даже не пытался разбираться т.к. мне UE нужен для применения в MMO, а тут типовые механизмы бессильны.

если смогу чем то помочь по написанию своей сети то спашивайте.


Можно по-подробней, что представляет из себя блок для UE? В его задачи входит обработка трафика с сервера, создание и управление объектами UE? Какие классы UE были переопределены для его подключения?
Для сервера winsock2.h чистый или с использованием портов завершения?
Это уже работает или пока только в теории?
Аватара пользователя
Тех. администратор
Сообщения: 367
Изображение
Весь этот тред.

Чего только стоит формулировка сеть на winsock2.h... На самом деле winsock - это довольно таки кривая реализация BSD Sockets в Windows. Почему бы просто не сообщить всем что сеть на обыкновенных сокетах?
Впрочем, это сразу показывает, что всё намного хуже, чем можно подумать...

НО.

Всё это дилетантство, лень и нежелание разбираться в движке, в которым работаешь. В анриале ведь есть слой абстракции для TCP/UDP соединений - почему бы не воспользоваться им? Неет, нужно писать свой велосипед.

Может выложите сюда код, чтобы всем стало понятно о чём идёт речь? Я держу пари - там есть над чем посмеяться, точнее откровенно поржать, потому как наверняка не учтены какие-нибудь фундаментальные вещи, приводящие к абсолютно известным и решаемым проблемам. Нет, ну если написано всё как надо, я конечно, извинюсь за свои слова, но я почему-то уверен что проблем в коде предостаточно.
Аватара пользователя
Пользователь
Сообщения: 71
рад буду услышать конструктивную критику а не пафос который впереди вас идет

Код:
void NetManager::addNetListener(int port, int pckExecutorCnt, int netConnectionLimit, bool logPcks, NetPacketHandler* pckHandler)
{
   char buff[1024];
   if (WSAStartup(0x0202, (WSADATA *)&buff[0]))
   {
      _loger->LogError("NetManager", "Error: WSAStartup");
      delete(pckHandler);
      return;
   }

   SOCKET server_Socket;
   if ((server_Socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      _loger->LogError("NetManager", "Error: Init Socket");
      WSACleanup();
      delete(pckHandler);
      return;
   }
   sockaddr_in local_addr;
   local_addr.sin_family = AF_INET;
   local_addr.sin_port = htons(port);
   local_addr.sin_addr.s_addr = 0;

   if (bind(server_Socket, (sockaddr *)&local_addr, sizeof(local_addr)))
   {
      _loger->LogError("NetManager", "Error: Bind");
      closesocket(server_Socket);
      WSACleanup();
      delete(pckHandler);
      return;
   }
   if (listen(server_Socket, netConnectionLimit))
   {
      _loger->LogError("NetManager", "Error: Listen");
      closesocket(server_Socket);
      WSACleanup();
      delete(pckHandler);
      return;
   }

   bool l = true;
   if (ioctlsocket(server_Socket, FIONBIO, (unsigned long*)&l))
   {
      _loger->LogError("NetManager", "Error: NonBlocking switch");
      closesocket(server_Socket);
      WSACleanup();
      delete(pckHandler);
      return;
   }

   ListenerThreadClass * newListenerClass = new ListenerThreadClass();
   newListenerClass->pckExecutorCnt = pckExecutorCnt;
   newListenerClass->server_Socket = server_Socket;
   newListenerClass->threadId = to_string(port);
   newListenerClass->packetHandler = pckHandler;
   newListenerClass->netConnectionLimit = netConnectionLimit;
   newListenerClass->logPcks = logPcks;
   listenerThreads.push_back(newListenerClass);

   unsigned threadID;
   _beginthreadex(NULL, 0, &NetListenerThread, newListenerClass, 0, &threadID);
}


unsigned __stdcall NetManager::NetListenerThread(void * pars)
{
   _set_se_translator(trans_func);
   ListenerThreadClass *listenerThread = (ListenerThreadClass *)pars;
   _loger->Log("NetManager listenerThread_" + listenerThread->threadId, "Started. Connection limit = " + to_string(listenerThread->netConnectionLimit));

   unsigned threadID;
   ExecutorThreadClass * newExecutorClass;
   for (int x = 1; x <= listenerThread->pckExecutorCnt; x++)
   {
      newExecutorClass = new ExecutorThreadClass();
      newExecutorClass->threadId = listenerThread->threadId + "-" + to_string(x);
      newExecutorClass->packetHandler = listenerThread->packetHandler;
      newExecutorClass->logPcks = listenerThread->logPcks;
      listenerThread->executorThreads.push_back(newExecutorClass);
      _beginthreadex(NULL, 0, &NetExecutorThread, newExecutorClass, 0, &threadID);
   }

   SOCKET client_Socket = NULL;
   sockaddr_in client_addr;
   int client_addr_size = sizeof(client_addr);
   NetClient * newNetClient;
   unsigned int t_min;
   int activeNetClientsCnt;
   deque<ExecutorThreadClass*>::iterator etIter;
   ExecutorThreadClass* minUsedThread;

   while (!listenerThread->stopThread)
   {
      client_Socket = accept(listenerThread->server_Socket, (sockaddr *)&client_addr, &client_addr_size);
      if (client_Socket != INVALID_SOCKET)
      {
         activeNetClientsCnt = 0;
         t_min = UINT_MAX;
         for (etIter = listenerThread->executorThreads.begin(); etIter != listenerThread->executorThreads.end(); etIter++)
         {
            activeNetClientsCnt += (*etIter)->clientQueue.size();
            if ((*etIter)->clientQueue.size() < t_min)
            {
               minUsedThread = *etIter;
               t_min = (*etIter)->clientQueue.size();
            }
         }
         if(listenerThread->logPcks)
            _loger->Log("NetManager listenerThread_" + listenerThread->threadId, "Accept connection from " + string(inet_ntoa(client_addr.sin_addr)) + ":" + to_string(ntohs(client_addr.sin_port)));

         if (activeNetClientsCnt < listenerThread->netConnectionLimit)
         {
            newNetClient = (listenerThread->packetHandler)->createNewNetClient();
            newNetClient->client_Socket = client_Socket;
            newNetClient->remoteAddr = inet_ntoa(client_addr.sin_addr);
            newNetClient->remotePort = ntohs(client_addr.sin_port);

            minUsedThread->addClient(newNetClient);
            newNetClient->onConnect();
         }
         else
         {
            if (listenerThread->logPcks)
               _loger->Log("NetManager listenerThread_" + listenerThread->threadId, "Max connection Limit. Disconnect connection from " + string(inet_ntoa(client_addr.sin_addr)) + ":" + to_string(ntohs(client_addr.sin_port)));
            closesocket(client_Socket);
         }
      }
      Sleep(1);
   }

   closesocket(listenerThread->server_Socket);
   for (etIter = listenerThread->executorThreads.begin(); etIter != listenerThread->executorThreads.end(); etIter++)
   {
      (*etIter)->stopThread = true;
   }
   bool allStoped = false;
   while (!allStoped)
   {
      allStoped = true;
      for (etIter = listenerThread->executorThreads.begin(); etIter != listenerThread->executorThreads.end(); etIter++)
      {
         if (!(*etIter)->threadStoped)
            allStoped = false;
      }
      Sleep(1);
   }
   for (etIter = listenerThread->executorThreads.begin(); etIter != listenerThread->executorThreads.end(); etIter++)
   {
      delete(*etIter);
   }
   delete(listenerThread->packetHandler);
   _loger->Log("NetManager listenerThread_" + listenerThread->threadId, "Stoped");
   listenerThread->threadStoped = true;
   return 0;
}

unsigned __stdcall NetManager::NetExecutorThread(void * pars)
{
   _set_se_translator(trans_func);
   ExecutorThreadClass *executorThread = (ExecutorThreadClass *)pars;
   _loger->Log("NetManager executorThread_" + executorThread->threadId, "Started");
   NetPacket * pckToExecute = NULL;
   int bytes_recv;
   BYTE *buff = new BYTE[20 * 1024];
   unsigned int currPos;
   unsigned int pckSize;
   NetPacket *pck;
   deque<NetClient*>::iterator cqIter;
   deque<NetPacket*>::iterator pqIter;

   while (!executorThread->stopThread)
   {
      executorThread->lockQueue();
      for (cqIter = executorThread->clientQueue.begin(); cqIter != executorThread->clientQueue.end();)
      {
         bytes_recv = recv((*cqIter)->client_Socket, (char*)buff, (20 * 1024), 0);
         if (bytes_recv > 0)
         {
            currPos = 0;
            while (bytes_recv > 0)
            {
               pckSize = (executorThread->packetHandler)->getpacketLen(buff + currPos);
               if ((pckSize == 0) || pckSize > (unsigned int)bytes_recv)
               {
                  pckSize = bytes_recv;
                  if (executorThread->logPcks)
                     _loger->Log("NetManager executorThread_" + executorThread->threadId, "Incorrect packet lenght");
               }
               (executorThread->packetHandler)->decrypt(buff + currPos, pckSize);
               pck = (executorThread->packetHandler)->packetHandle(buff + currPos, pckSize);
               bytes_recv -= pckSize;
               if (pck != NULL) {
                  pck->setBuff(buff + currPos, (executorThread->packetHandler)->getDataOffset(), pckSize);
                  pck->setNetClient(*cqIter);
                  executorThread->pckQueue.push_back(pck);
               }
               else
                  (*cqIter)->onIncorrectPck();
               if (executorThread->logPcks)
                  _loger->LogPacket(&buff[currPos], pckSize, pck, (*cqIter)->remoteAddr, "Client");
               currPos += pckSize;
            }
            cqIter++;
         }
         else
         {
            if (WSAGetLastError() != WSAEWOULDBLOCK)
            {
               if (executorThread->logPcks)
                  _loger->Log("NetManager executorThread_" + executorThread->threadId, "Client " + (*cqIter)->remoteAddr + ":" + to_string((*cqIter)->remotePort) + " disconnected");
               (*cqIter)->onDisconnect();
               (*cqIter)->disconnect();
               delete(*cqIter);
               cqIter = executorThread->clientQueue.erase(cqIter);
            }
            else
               cqIter++;
         }
      }
      executorThread->unlockQueue();

      while (executorThread->pckQueue.size() > 0)
      {
         pqIter = executorThread->pckQueue.begin();
         pckToExecute = (*pqIter);
         executorThread->pckQueue.erase(pqIter);
         if (pckToExecute != NULL)
         {
            try
            {
               pckToExecute->read();
            }
            catch (SE_Exception e)
            {
               _loger->LogError("NetManager executorThread_" + executorThread->threadId, "Caught exception on " + pckToExecute->getName());
               _loger->printStackTrace(e.getContext());
            }
            delete(pckToExecute);
            pckToExecute = NULL;
         }
      }
      Sleep(1);
   }

   _loger->Log("NetManager executorThread_" + executorThread->threadId, "Has active clients : " + to_string(executorThread->clientQueue.size()));
   int succesDisconnectClientCnt = 0;
   executorThread->lockQueue();
   for (cqIter = executorThread->clientQueue.begin(); cqIter != executorThread->clientQueue.end();)
   {
      (*cqIter)->onDisconnect();
      (*cqIter)->disconnect();
      delete(*cqIter);
      cqIter = executorThread->clientQueue.erase(cqIter);
      succesDisconnectClientCnt++;
   }
   _loger->Log("NetManager executorThread_" + executorThread->threadId, "Successful disconnect clients : " + to_string(succesDisconnectClientCnt));
   delete(buff);
   _loger->Log("NetManager executorThread_" + executorThread->threadId, "Stoped");
   executorThread->threadStoped = true;
   return 0;
}
Аватара пользователя
Тех. администратор
Сообщения: 367
MHard писал(а):
не пафос который впереди вас идет

Неплохо проиграл с этого %)

А можно ещё то, как вы это дело всё-таки используете? А то я ни одного send-а не увидел. Как вызываете там, итп. Хендлеры пакетов те-же. И желательно чтобы это что-то можно было собрать и погонять под вайршарком. И главное - собственно, где анриал то?
Вот как всё это будет - проведём сравнение вашей реализации с реализацией анриала.

PS: уже предвкушаю - у вас тут TCP, за каким-то макаром несколько листенеров, спинлоки со слипом вместо нормальных селектов хотябы, и куча абсолютно ненужных тредов... Будет весело %)
Аватара пользователя
Пользователь
Сообщения: 71
MOZGIII писал(а):
И желательно чтобы это что-то можно было собрать и погонять под вайршарком.


ключи от машины не дать вам погонять? ))

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

всего вам доброго.
Аватара пользователя
Тех. администратор
Сообщения: 367
Да уже и не надо чтобы было что собрать - это я просто вчитаться не успел. Всё и так понятно. Ваш код такой никому и даром не нужен - подучите всё-таки основы и паттерны. Любопытных частей, вроде сериализации этих самых пакетов или какого-либо взаимодействия с большим и сложным игровым движком, я так и не увидел - но могу поспорить что там ещё более неграмотно организованный велосипед, а по производительности не сравнится даже с каким-нибудь ракнетом, не то что эпиковской сетевой подсистемой.
Справедливости ради, отмечу что задумка у вас была хорошая, но реализация оставляет желать лучшего.
Хотя, и к задумке претензии есть, и не мало.

Да, и заметьте - я уже вам в PS написал достаточно много конструктивных вещей - это проблемы реальны, и я не придумал их, а обнаружил в скудном куске вашего кода. Подумайте лучше над тем, почему это проблемы, и как их исправить. А иначе я не завидую тем, кто в ваши поделки потом будет играть пытаться.

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

PS: мда, да и вообще код на С++ у вас написан в стиле С. Отличная работа, так держать.
Аватара пользователя
Пользователь
Сообщения: 1297
to MOZGIII
Чего ты злющий-то такой =)? Форум вроде не для тыкания лицом в грязь, а для помощи. Причем тех кто хочет помогать, те кто не хотят, шли бы мимо.
Я уверен MHard не сидит и целыми днями не пишет профессиональный код для эпиков, валве и подобных. И тут далеко не все работаю в сфере гейм дева, дабы тыкать их, что они такое дно. Просто кто-то захотел переключится, а для кого-то просто баловство. А кто-то вырастит во что-то большее, благодаря тем кто помогает. И в этом нет ничего плохого. Этим и отличается к сожалению Россия от запада, там стараются как никак помогать. Буржуйские форумы же читаете.
Давайте жить дружно ребята. )
_________________
Мои работы.
Youtube Channel
Форум по геймдеву.
Аватара пользователя
Тех. администратор
Сообщения: 367
Deus Ex Machina
Только лишь из-за нежелания человек разобраться в том коде, который уже есть. Человек явно не грамотный, но при этом считает что он, во первых в состоянии написать годный код - и как мы видим - это не так, по вторых считает себя умнее всех (это ещё отдельная тема) - но и всем рекомендует вместо более правильного подхода (т.е. научиться пользоваться тем, что в движке есть) реализовывать свои велосипеды, что, очевидно, многократно сложнее, особенно для новичков, которые и в просто игровом программировании ни бум-бум, не то, что в сетевом.

Да и тут, на самом деле, есть нюанс: сеть в анриале глубоко зашита в архитектуру. То, что предоставил MHard действительно не имеет отношения к анриалу, а ещё это действительно довольно посредственный код, с кучей проблем. Учитывая, что в анриале есть абстракции сетевых транспортов, в данном случае намного уместнее было бы реализовывать это дело в виде имплементации как раз такого транспорта. But wait, there's more! Сериализация в анриале, можно сказать, уже пришла к успеху - всё хорошо абстрагировано, в меру оптимизировано и автоматизировано. При этом есть куча инструментов для отладки, вариантов использования, а ограничений по производительности практически никаких нет. На анриале (если говорить о только встроенных возможностях) можно даже MMO написать, правда, для этого нужно очень хорошо понимать, как в MMO работает сеть - что устроить всё так, чтобы анриал мог держать нужную нагрузку.

Да, и, как можно видеть из других постов - такое отношение у меня далеко не ко всем, а только лишь к тем, кто неграмотен, не по шансам оценивает свои силы, но при этом зазнаётся и вступает в бессмысленные споры.
Но дело не только в этом. Почитайте тред, я некоторое время по нему не отвечал, но когда понял, что мысли в целом уходят не туда - решил всё-таки отписаться. Тут, скорее уже общий подход неправильный - и я выказываюсь против него на конкретном примере. Попробовали на худой конец тот-же ракнет приспособить, а лучше ACE - это было б куда занимательнее, хоть и всё равно не очень полезно. Но ведь там тоже сначала изучить их надо. %)

Кстати, форумы читать вообще не обязательно. А вот ман - по сокетам в данном случае - обязательно. %)


Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

UEngine.ru © 2017
Все права защищены. При копировании материалов с сайта, ссылка на первоисточник обязательна.
Яндекс.Метрика
Главная страница