gpt4 book ai didi

c++ - WriteFileEx 完成例程成功,但传输的字节数不正确

转载 作者:可可西里 更新时间:2023-11-01 12:44:06 25 4
gpt4 key购买 nike

我使用 IO 完成例程通过管道在不同机器上的两个进程之间进行通信。

有时,当调用 WriteFileEx 的完成例程时,完成例程参数 dwErrorCode 为 0(即无错误),GetOverlappedResult 返回 true(即无错误),但 dwNumberOfBytesTransfered 与 WriteFileEx 调用中的 nNumberOfBytesToWrite 不匹配。然而,我只在管道的客户端看到了这一点。

如果传输的字节数与请求传输的字节数不匹配,如何才能视为成功?

客户端的管道句柄是这样创建的:

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];

编辑:

在尝试按照 Harry 的建议重新初始化重叠结构后,我注意到了一些奇怪的事情。我在每个 WriteFileEx 之前将 memset OVERLAPPED 结构归零,并且大约 1/5000 完成例程回调,cbWritten参数和 OVERLAPPED 结构的 InternalHigh 成员现在设置为上一条消息的大小,而不是最新消息的大小。我在完成例程内的管道的客户端和服务器端都向文件添加了一些日志记录,并且两端发送和接收的数据完全匹配(并且是正确的预期数据)。这随后揭示了在将数据写入文件所花费的时间中,OVERLAPPED 结构中的 InternalHigh 成员已更改为现在反射(reflect)我所期望的消息的大小(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 位上调用完成例程。

This MSDN page说:

"The system does not use the OVERLAPPED structure after the completion routine is called, so the completion routine can deallocate the memory used by the overlapped structure."

...很明显,这段代码可以重现的事情永远不应该发生?

这是 WINAPI 错误吗?

最佳答案

CreateFile 调用中添加了 FILE_FLAG_NO_BUFFERING - 从那以后就没有发现问题了。感谢所有抽出宝贵时间发表评论的人。

关于c++ - WriteFileEx 完成例程成功,但传输的字节数不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13518045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com