Плагин для сокета C TCP

#c #windows #sockets #plugins #tcp

#c #Windows #сокеты #Плагины #tcp

Вопрос:

В настоящее время я работаю с движком моделирования VBS2 и пытаюсь написать плагин TCP socket. У меня есть клиентское приложение, которое я хочу подключить к плагину и отправить одно сообщение. Возможно, это будет иметь больше смысла, если я опубликую существующий код плагина:

 #include <windows.h>
#include "VBSPlugin.h"

// Command function declaration
typedef int (WINAPI * ExecuteCommandType)(const char *command, char *result, int resultLength);

// Command function definition
ExecuteCommandType ExecuteCommand = NULL;

// Function that will register the ExecuteCommand function of the engine
VBSPLUGIN_EXPORT void WINAPI RegisterCommandFnc(void *executeCommandFnc)
{
  ExecuteCommand = (ExecuteCommandType)executeCommandFnc;
}

// This function will be executed every simulation step (every frame) and took a part     in the simulation procedure.
// We can be sure in this function the ExecuteCommand registering was already done.
// deltaT is time in seconds since the last simulation step
VBSPLUGIN_EXPORT void WINAPI OnSimulationStep(float deltaT)
{
  //{ Sample code:
ExecuteCommand("0 setOvercast 1", NULL, 0);
  //!}
}

// This function will be executed every time the script in the engine calls the script function "pluginFunction"
// We can be sure in this function the ExecuteCommand registering was already done.
// Note that the plugin takes responsibility for allocating and deleting the returned string
VBSPLUGIN_EXPORT const char* WINAPI PluginFunction(const char *input)
{
  //{ Sample code:
  static const char result[]="[1.0, 3.75]";
  return resu<
  //!}
}

// DllMain
BOOL WINAPI DllMain(HINSTANCE hDll, DWORD fdwReason, LPVOID lpvReserved)
{
   switch(fdwReason)
   {
      case DLL_PROCESS_ATTACH:
         OutputDebugString("Called DllMain with DLL_PROCESS_ATTACHn");
         break;
      case DLL_PROCESS_DETACH:
         OutputDebugString("Called DllMain with DLL_PROCESS_DETACHn");
     break;
      case DLL_THREAD_ATTACH:
         OutputDebugString("Called DllMain with DLL_THREAD_ATTACHn");
         break;
      case DLL_THREAD_DETACH:
         OutputDebugString("Called DllMain with DLL_THREAD_DETACHn");
         break;
   }
   return TRUE;
}
  

Сообщение, отправленное плагину, будет использовано в функции OnSimulationStep() путем передачи в качестве аргумента ExecuteCommand(). Тем не менее, я также должен быть осторожен с блокировкой здесь, поскольку функции OnSimulationStep () должно быть разрешено запускать каждый шаг моделирования.

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

Заранее спасибо, все советы высоко ценятся.

Комментарии:

1. Было бы полезно, если бы вы рассказали нам, чего вы хотите достичь. Если вы пытаетесь сделать что-то сложным способом, мы можем предложить более простую альтернативу. Вам действительно нужен tcp или вы просто заинтересованы в передаче сообщений между процессами / потоками?

2. Боюсь, я не совсем уверен, что вы имеете в виду; я пытаюсь заставить плагин прослушивать входящее сообщение от клиента, и если сообщение было получено, оно передается ExecuteCommand() . Я выбрал TCP, потому что я знаю, что клиенты, которые написаны на C #, написаны для TCP. Отвечает ли этот вид на ваш вопрос? Спасибо

3. Существуют другие технологии, которые могут быть проще или лучше для решения вашей проблемы. Если мы не знаем ваших требований или проблемы, которую вы пытаетесь решить, мы ограничены в том, насколько мы можем помочь. Мы не можем найти выход из леса, потому что вы рассказали нам только об одном дереве. Вы рассматривали MSMQ или WCF?

4. Мои искренние извинения, но я действительно не понимаю, что вы имеете в виду, говоря о незнании проблемы; проблема действительно так проста, как я ранее заявлял. Этот плагин является ASI к рассматриваемой программе. У меня есть клиент, отдельно написанный на C #, который пытается подключиться через TCP и отправить действительные сообщения скрипта, такие как пример в плагине «0 setOvercast 1». Я просто хочу получать эти сообщения и передавать их в качестве аргумента ExecuteCommand() . Я ничего не скрываю; в этом нет ничего более сложного, чем это — MSMQ и WCF, похоже, сильно усложняют проблему. Продолжение…

5. … Я ни в коем случае не хочу показаться грубым или неблагодарным, я действительно ценю время и усилия, я просто пытаюсь понять, какой информации не хватает в проблеме. Я с удовольствием попытаюсь предоставить дополнительную информацию, но я не уверен, какая дополнительная информация необходима. 🙂

Ответ №1:

Я бы лично выбрал boost:: asio, чтобы избавить себя от всех хлопот при работе с асинхронным вводом-выводом.

Он относительно прост в использовании и хорошо работает в среде плагинов — я делал нечто подобное (также в VBS2).

Ответ №2:

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

Одним из вариантов является очередь в вашем плагине и рабочий поток, который перекачивает данные из очереди в сокет. С дополнительным потоком вы можете просто использовать потенциальный блокирующий вызов. Если блокирующий вызов l является для вас проблемой, вы можете перевести сокет в неблокирующий режим и с WSAAsyncSelect ждать события, указывающего, что вы можете снова выполнить запись в одноранговый узел.

Ответ №3:

Вы могли бы реализовать TCP-сервер, который хранит входящие сообщения в упорядоченном списке. На каждом этапе моделирования вы затем запрашиваете полученные сообщения у TCP-сервера и применяете их к VBS2 через ExecuteCommand.

Не забывайте всегда использовать ExecuteCommand в потоке, который вызывает OnSimulationStep. Это означает, что вы не можете выполнять входящие сообщения непосредственно на TCP-сервере.