2015-03-09 2 views
0

я нашел этот StackOverflow вопрос:Отправка структур данных через именованные каналы

Create Named Pipe C++ Windows

И создали этот класс:

#pragma once 

#define PIPE_FD TEXT("\\\\.\\pipe\\somepipe") 

#define BUFFER_SIZE 1024 

// CPipe Class 
class CPipe 
{ 

private: 

    // 
    // Variables 
    // 

    HANDLE hPipe; 
    char buffer[BUFFER_SIZE]; 
    DWORD dwRead; 
    DWORD dwWritten; 

public: 

    bool CreatePipe() 
    { 
     hPipe = CreateNamedPipe(PIPE_FD, PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, PIPE_WAIT, 1, BUFFER_SIZE * 16, BUFFER_SIZE * 16, NMPWAIT_USE_DEFAULT_WAIT, NULL); 

     return (hPipe == NULL) ? false : true; 
    } 

    bool CreatePipeFile() 
    { 
     hPipe = CreateFile(PIPE_FD, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 

     return (hPipe == NULL) ? false : true; 
    } 

    void Destroy() 
    { 
     DisconnectNamedPipe(hPipe); 
    } 

    bool IsPipe() 
    { 
     return (hPipe == NULL) ? false : true; 
    } 

    bool IsConnected() 
    { 
     return (ConnectNamedPipe(hPipe, NULL) != FALSE) ? true : false; 
    } 

    void Read() 
    { 
     while (ReadFile(hPipe, buffer, sizeof(buffer), &dwRead, NULL) != FALSE) 
     { 
      /* do something with data in buffer */ 
      printf("%s", buffer); 
     } 
    } 

    void Write() 
    { 
     WriteFile(hPipe, "Hello Pipe\n", 12, &dwWritten, NULL); 

     CloseHandle(hPipe); 
    } 
}; 

extern CPipe gPipe; 

Главный процесс:

gPipe.CreatePipe(); 
    while (gPipe.IsPipe()) 
    { 
     if (gPipe.IsConnected()) 
     { 
      gPipe.Read(); 
     } 

     gPipe.Destroy(); 
    } 

Пульт дистанционного управления:

gPipe.CreatePipeFile(); 
    if (gPipe.IsPipe()) 
    { 
     gPipe.Write(); 
    } 

Который прекрасно работает. Я могу отправить «Hello Pipe \ n» между двумя приложениями. Тем не менее, я пытаюсь изменить его для отправки структур данных, а не строк.

Например, эта структура:

struct Test_t 
{ 
    int x; 
    int y; 
    float J[3]; 
    bool Yes; 
}; 

Таким образом, клиент может отправить структуру по трубе, и сервер может прочитать структуру от трубы и обновление локальных структур сервера соответственно.

Я попытался:

reinterpret_cast<char*>(&test);

Но я не мог заставить его работать. Есть идеи?

Любая помощь приветствуется.

+0

Просто, чтобы предупредить вас, если вы измените эту структуру на не-POD, ваш метод просто передать всю структуру не будет работать. – PaulMcKenzie

ответ

0

переинтерпретировать литая, вероятно выглядеть следующим образом:

reinterpret_cast<void*>(&test); 

Вы также должны убедиться, что вы получите количество данных для передачи права (SizeOf ваш друг здесь).

Обратите внимание, что отправка таких структур может стать рискованным.

  • Отправленные объекты должны быть простыми старыми объектами данных или они не будут правильно сериализованы. См. What are POD types in C++? для получения дополнительной информации о простых старых данных. Элементы указателя, виртуальные функции и т. Д. Не будут работать.
  • Если два процесса, говорящих друг с другом, имеют разные представления о структуре упаковки, то с другой стороны это будет неправильно. До тех пор, пока вы полностью контролируете среду сборки, это должно быть хорошо, но когда все начинает ломаться, вы можете получить некоторые действительно неприятные ошибки для исправления.

Если у вас нет экстремальных соображений производительности, вы должны изучить более организованный способ сериализации данных, которые вы отправляете по каналу, таких как буферы протокола google или boost :: serialize, чтобы убедиться, что формат провода немного менее хрупкий. буферы протоколов (и многие другие технологии) имеют то преимущество, что они не являются специфичными для C++, поэтому вы можете говорить между процессами, созданными на разных языках программирования.

Смежные вопросы