Процедура завершения WriteFileEx выполнена успешно, но переданные байты неверны

Я связываюсь между двумя процессами на разных машинах через канал, используя процедуры завершения ввода-вывода.

Иногда, когда вызывается подпрограмма завершения для WriteFileEx, параметр подпрограммы завершения dwErrorCode равен 0 (т. Е. Без ошибок), GetOverlappedResult возвращает true (т. Е. Без ошибок), но dwNumberOfBytesTransfered не соответствует nNumberOfBytesToWrite в вызове WriteFileEx. Однако я вижу это только на стороне клиента.

Если количество переданных байтов не соответствует количеству байтов, которое было запрошено для передачи, как это можно считать успешным?

Вот как создается дескриптор клиента для канала:

mHPipe = CreateFile(pipeName,                 // pipe name
GENERIC_READ |            // read and write access
GENERIC_WRITE,
0,                        // no sharing
NULL,                     // default security attributes
OPEN_EXISTING,            // opens existing pipe
FILE_FLAG_OVERLAPPED |    // overlapped
FILE_FLAG_WRITE_THROUGH,  // write through mode
NULL);                    // no template file

// do some checking...

// The pipe connected; change to message-read mode.
DWORD dwMode = PIPE_READMODE_MESSAGE;
BOOL fSuccess = SetNamedPipeHandleState(mHPipe,   // pipe handle
&dwMode,  // new pipe mode
NULL,     // don't set maximum bytes
NULL);    // don't set maximum time

Кто-нибудь может понять, почему это произошло?

Спасибо

РЕДАКТИРОВАТЬ:

Соответствующий код WriteFileEx выглядит следующим образом:

void WINAPI CompletedWriteRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverLap)
{
BOOL fWrite = FALSE;
LPPIPEINST lpPipeInst = (LPPIPEINST)lpOverLap;

//
// !  99.9% of the time, dwNumberOfBytesTransfered == lpPipeInst->cbDataSize
//    but 0.1% of the time, they do not match
//

// Some stuff

// Copy next message to send
memcpy_s(lpPipeInst->chData, sizeof(lpPipeInst->chData), pMsg->msg, pMsg->size);
lpPipeInst->cbDataSize = pMsg->size;

// Some other stuff

fWrite = WriteFileEx(lpPipeInst->hPipeInst,
lpPipeInst->chData,
lpPipeInst->cbDataSize,
(LPOVERLAPPED) lpPipeInst,
(LPOVERLAPPED_COMPLETION_ROUTINE)CompletedWriteRoutine);

// Some other, other stuff
}

Где LPPIPEINST объявлен как:

typedef struct
{
OVERLAPPED oOverlap;      // must remain first item
HANDLE hPipeInst;
TCHAR chData[BUFSIZE];
DWORD cbDataSize;
} PIPEINST, *LPPIPEINST;

И первоначальный вызов CompletedWriteRoutine получает параметр lpOverlap, объявленный так:

PIPEINST pipeInstWrite        = {0};
pipeInstWrite.hPipeInst       = client.getPipeHandle();
pipeInstWrite.oOverlap.hEvent = hEvent[eventWriteComplete];

РЕДАКТИРОВАТЬ:

После попытки заново инициализировать перекрывающуюся структуру, как предложил Гарри, я заметил нечто странное.
я memset OVERLAPPED структура к нулю перед каждым WriteFileExи примерно 1/5000 стандартных обратных вызовов, cbWritten параметр и OVERLAPPED структура-х InternalHigh элемент member теперь был настроен на размер предыдущего сообщения вместо самого последнего сообщения. Я добавил некоторые записи в файл как на клиентском, так и на серверном концах канала внутри подпрограмм завершения, и данные, отправленные и полученные на обоих концах, имели точное совпадение (и правильные, ожидаемые данные). Это тогда показало, что за время, необходимое для записи данных в файл, InternalHigh член в OVERLAPPED структура изменилась и теперь отражает размер ожидаемого сообщения (cbWritten остается старый размер сообщения). Я удалил ведение журнала файлов и теперь могу воспроизвести проблему как часы с этим кодом:

void WINAPI CompletedWriteRoutine(DWORD dwErr, DWORD cbWritten, LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst = (LPPIPEINST)lpOverLap;

// Completion routine says it wrote the amount of data from the previous callback
if (cbWritten != lpPipeInst->cbDataSize)
{
// Roughly 1 in 5000 callbacks ends up in here

OVERLAPPED ovl1 = lpPipeInst->oOverlap; // Contains size of previous message, i.e. cbWritten
Sleep(100);
OVERLAPPED ovl2 = lpPipeInst->oOverlap; // Contains size of most recent message, i.e lpPipeInst->cbDataSize
}
...
}

Иногда кажется, что процедура завершения вызывается перед OVERLAPPED структура и входной параметр подпрограммы завершения обновляются. я использую MsgWaitForMultipleObjectsEx(eventLast, hEvent, INFINITE, QS_POSTMESSAGE, MWMO_ALERTABLE); для выполнения процедур завершения в Windows 7 64 бит.

Эта страница MSDN говорит:

«Система не использует структуру OVERLAPPED после вызова процедуры завершения, поэтому процедура завершения может освободить память, используемую перекрытой структурой».

…так очевидно, что этот код может воспроизвести никогда не должно произойти?

Это ошибка WINAPI?

9

Решение

добавленной FILE_FLAG_NO_BUFFERING к CreateFile позвоните — не видел проблемы с тех пор. Спасибо всем, кто прокомментировал ваше время.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]