使用完成端口来编写的一个程序,使用WSASend来投递数据,返回值表示已经成功了。
在完成端口的服务线程中,GetQueuedCompletionStatus结果为False,使用WSAGetLastError查到的错误是6,搜了一下,其中有个回答是OVERLAPPED 里的hEvent无效,但我已经用WSACreateEvent赋值了。 str := Edit1.Text + chr($D); new(PerIoData);
for k:= 1 to Length(str) do
PerIoData.Buffer[k-1] := str[k]; ZeroMemory(@(PerIoData.Overlapped), sizeof(OVERLAPPED));
PerIoData.Overlapped.hEvent := WSACreateEvent(); PerIoData.DataBuf.buf := @PerIoData.Buffer;
PerIoData.DataBuf.len := DATA_BUFSIZE;//length(str);
PerIoData.IOType := ioWrite;
if (WSASend(m_socket, @(PerIoData.DataBuf), 1, @SendBytes, 0, @(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin
self.Memo1.Lines.Add('WSASend() failed with error');
end;
end;LPPER_IO_OPERATION_DATA = ^ PER_IO_OPERATION_DATA ;
PER_IO_OPERATION_DATA = packed record
Overlapped: WSAOVERLAPPED;
DataBuf: TWSABUF;
Buffer: array [0..DATA_BUFSIZE] of CHAR;
BytesSEND: DWORD;
BytesRECV: DWORD; IOType :TIOType;
end;
在完成端口的服务线程中,GetQueuedCompletionStatus结果为False,使用WSAGetLastError查到的错误是6,搜了一下,其中有个回答是OVERLAPPED 里的hEvent无效,但我已经用WSACreateEvent赋值了。 str := Edit1.Text + chr($D); new(PerIoData);
for k:= 1 to Length(str) do
PerIoData.Buffer[k-1] := str[k]; ZeroMemory(@(PerIoData.Overlapped), sizeof(OVERLAPPED));
PerIoData.Overlapped.hEvent := WSACreateEvent(); PerIoData.DataBuf.buf := @PerIoData.Buffer;
PerIoData.DataBuf.len := DATA_BUFSIZE;//length(str);
PerIoData.IOType := ioWrite;
if (WSASend(m_socket, @(PerIoData.DataBuf), 1, @SendBytes, 0, @(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin
self.Memo1.Lines.Add('WSASend() failed with error');
end;
end;LPPER_IO_OPERATION_DATA = ^ PER_IO_OPERATION_DATA ;
PER_IO_OPERATION_DATA = packed record
Overlapped: WSAOVERLAPPED;
DataBuf: TWSABUF;
Buffer: array [0..DATA_BUFSIZE] of CHAR;
BytesSEND: DWORD;
BytesRECV: DWORD; IOType :TIOType;
end;
我跟踪了几次,GetQueuedCompletionStatus每次的返回了false,根本就没有成功过,这令我很困惑。
begin
getData := GetQueuedCompletionStatus(m_hCompletionPort, BytesTransferred,
DWORD(PerHandleData), POverlapped(PerIoData), INFINITE); if getData then
....
else
...endgetData永远都返回False,PerIoData值为nil。不知道是不是WSASend的时候,PerIoData内存没有分配到堆上,还是什么别的原因。
我一开始是这样初始化的,CreateIoCompletionPort(INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0),因为第二个参数ExistingCompletionPort: THandle的类型是个句柄值,所以我就传了一个NVALID_HANDLE_VALUE。把这个参数传个0就正常了,就像下边这样:
CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);因为这个过程挺简单的,我都没有想到去检查这个地方。
再次感谢两位,帮了我大忙了。