Что я использую в качестве замены GetFileSize () для каналов? - PullRequest
2 голосов
/ 12 сентября 2011

См. Заголовок.

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

Справка MSDN говорит:

Вы не можете использовать функцию GetFileSize с дескриптором незапрашиваемого устройства, такого как канал или устройство связи. Чтобы определить тип файла для hFile , используйте функцию GetFileType .

Хм. Хорошо. Но если я не могу использовать GetFileSize для определения объема данных, читаемых из канала, что я буду использовать тогда? В настоящее время я делаю

length = GetFileSize(pipehandle, 0);
while(length == 0){
  Sleep(10);                           // wait a bit
  length = GetFileSize(pipehandle, 0); // and try again
}

Рано или поздно length получает больший ноль, но ожидание кажется мне немного плохим.


Справочная информация: У меня есть трубочный сервер (примерно Многопоточный конвейерный сервер из примера MSDN ), который ожидает подключения клиента. После подключения сервер считывает содержимое файла и передает его клиенту, используя конвейерное соединение.


Дополнительная информация: Общая причина, по которой я хочу это сделать, заключается в том, что я работаю с внешней библиотекой, которая реализует синтаксический анализатор XML. Первоначально парсер открывает файл, затем к этому файлу применяется CreateFileMapping и, наконец, вызывается MapViewOfFile для получения содержимого файла.

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

В настоящее время я определяю размер данных в канале (я знаю, что они используются только один раз для передачи входного файла из App1 в App2), затем делаю malloc, чтобы получить буфер и прочитать весь контент трубы в этот буфер.

Если я нахожусь на трассе, я также буду открыт для любых предложений по улучшению ситуации.

Ответы [ 2 ]

2 голосов
/ 12 сентября 2011

Очевидно, что в этом случае вам нужен PIPE_TYPE_BYTE, поскольку объем данных непредсказуем. Обрабатывайте его так же, как обычный файл в клиенте, вызывая ReadFile (), повторяя его с небольшим буфером, скажем, 4096 байт. Если вам нужно сохранить его в массиве, вы можете сначала написать целое число, чтобы клиент знал, насколько большим будет массив.

1 голос
/ 12 сентября 2011

Если вы создали свой канал в типе PIPE_TYPE_MESSAGE, вы сможете использовать метод PeekNamedPipe для получения полного сообщения из канала.

Основное различие между PIPE_TYPE_MESSAGE и PIPE_TYPE_BYTE:

  • в типе MESSAGE, система управляет длиной значения, отправляемого в канал, просто попросите прочитать одно сообщение, и вы получите все сообщение (полезно для не слишком большого сообщения, чтобы не заполнить всю память)
  • в типе BYTE, вы должны управлять длиной данных, которые вы посылаете через канал. Возможно, протокол TLV может быть хорошим способом узнать размер ваших «сообщений» (возможно, часть T-типа звучит как бесполезная), затем вы можете прочитать содержимое в двух частях: во-первых, прочитайте первые байты, которые дадут вам размер сообщения, а затем прочитайте сообщение по частям, если вы не хотите переполнять память.
...