关于网友提出的“ 关于Socket模型 重叠IO 完成例程模型”问题疑问,本网通过在网上对“ 关于Socket模型 重叠IO 完成例程模型”有关的相关答案进行了整理,供用户进行参考,详细问题解答如下:
问题: 关于Socket模型 重叠IO 完成例程模型
描述: 有没有谁有实际的Delphi例子啊?我这边有一个但是这个例子只能接受连接却接收不到客户端发送过来的数据。单步调式的时候发现WorkerRoutine这个回调函数死活得不到执行.
下面是代码:(主窗体只是调用了WSAStartup和开启了TEventThread线程。)
unit thrAccept;
interface
uses
Windows,SysUtils,Classes,IdWinSock2,thrOverlap;
type
TEventThread = class(TThread)
private
FlistenSock: TSocket;
FListenEvent: WSAEVENT;
FRWThread: TOverlapThread;
protected
procedure Execute;override;
function InitSock: BOOL;
procedure FreeResource;
end;
implementation
uses frmMain;
procedure TEventThread.Execute;
var
ret: Integer;
ne: TWSANetworkEvents;
sock: TSocket;
adr: TSockAddr;
begin
if not InitSock() then
Exit;
FRWThread := TOverlapThread.Create(True);
FRWThread.FreeOnTerminate := True;
FRWThread.Resume;
while (not Terminated) do
begin
WSAWaitForMultipleEvents(1,@FListenEvent,False,ACCEPT_TIME_OUT,False);
FillChar(ne,SizeOf(ne),0);
WSAEnumNetworkEvents(FlistenSock,FListenEvent,@ne);
//此函数是FlistenEvent自动成为未传信状态,不再需要使用WSARetEvent
if (ne.lNetworkEvents and FD_ACCEPT) > 0 then
begin
if (ne.lNetworkEvents and FD_ACCEPT) > 0 then
begin
if ne.iErrorCode[FD_ACCEPT_BIT] <> 0 then
Continue;
ret := SizeOf(adr);
sock := accept(FlistenSock,@adr,@ret);
if sock = INVALID_SOCKET then
Continue;
end;
//不必关系其他事件,虽然客户端断开连接会ne.lNetWorkEvents == 0,但是本线程只负责accept,所以不响应其他事件
end;
end;
FreeResource;
end;
function TEventThread.InitSock:BOOL;
var
addr: TSockAddr;
begin
Result := False;
FlistenSock := socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
addr.sin_family := AF_INET;
addr.sin_port := htons(LISTEN_PORT);
addr.sin_addr.S_addr := htonl(INADDR_ANY);
bind(FlistenSock,@addr,SizeOf(SOCKADDR_IN));
FListenEvent := WSACreateEvent;
WSAEventSelect(FlistenSock,FListenEvent,FD_ACCEPT);
listen(FlistenSock,5);
Result := True;
end;
procedure TEventThread.FreeResource;
begin
closesocket(FlistenSock);
WSACloseEvent(FListenEvent);
end;
end.
//------------------------------------------------------------------------------------------------------------//------------------------------------------------------------------------------------------------------------
unit thrOverlap;
interface
uses Windows,SysUtils,Classes,IdWinSock2,WinSock;
const
BUFFER_SIZE = 4096;
ACCEPT_TIME_OUT = 550;
RECV_TIME_OUT = 550;
type
TOverlapThread = class(TThread)
private
FBuf: WSABUF;
public
m_socket: TSocket;
m_overlap: WSAOVERLAPPED;
protected
procedure Execute;override;
end;
procedure WorkerRoutine(const dwError,cbTransferred: DWORD;const lpOverlapped: LPWSAOVERLAPPED; const dwFlags: DWORD);stdcall;
implementation
uses frmMain;
procedure TOverlapThread.Execute;
var
dwTemp,dwFlag: DWORD;
begin
FBuf.len := BUFFER_SIZE;
FBuf.buf := AllocMem(BUFFER_SIZE);
dwFlag := 0;
FillChar(m_overlap,SizeOf(WSAOVERLAPPED),0);
m_overlap.hEvent := DWORD(Self);
WSARecv(m_socket,@FBuf,1,dwTemp,dwFlag,@m_overlap,WorkerRoutine);
//Form1.ListBox1.Items.Add('WSARecv');
//WSASend(
while (not Terminated) do
begin
if SleepEx(RECV_TIME_OUT,True) = WAIT_IO_COMPLETION then
begin
// WSARecv(m_socket,@FBuf,1,dwTemp,dwFlag,@m_overlap,WorkerRoutine);
end else
begin
Continue;
end;
end;
end;
procedure WorkerRoutine(const dwError,cbTransferred: DWORD;const lpOverlapped: LPWSAOVERLAPPED; const dwFlags: DWORD);
var
dwTemp,Flags: DWORD;
begin
Form1.ListBox1.Items.Add('IN');
if (dwError <> 0) or (cbTransferred = 0) then
begin
closesocket(TOverlapThread(lpOverlapped^.hEvent).m_socket);
Exit;
end;
Form1.ListBox1.Items.Add(TOverlapThread(lpOverlapped^.hEvent).FBuf.buf);
FillChar(TOverlapThread(lpOverlapped^.hEvent).FBuf.buf^,BUFFER_SIZE,0);
Flags := 0;
FillChar(lpOverlapped^,SizeOf(WSAOVERLAPPED),0);
if WSARecv(TOverlapThread(lpOverlapped^.hEvent).m_socket,@(TOverlapThread(lpOverlapped^.hEvent)).FBuf,1,dwTemp,Flags,@(TOverlapThread(lpOverlapped^.hEvent)).m_overlap,WorkerRoutine) = SOCKET_ERROR then
begin
;
end;
end;
end.
//结束
解决方案1: WorkerRoutine 函数中你直接调用进程中的对象“Form1.ListBox1.Items”
这样做是肯定错误的,
解决方案2: Sorry
是我脑子BUG了
解决方案3: 理解Socket通信的底层方法,也不要一上来就是重叠IO啊
先理解原始的api实现socket,才是最好的
解决方案4: 自己写有太多未知情况,需要长时间的修改,一般的使用,Indy或者ServerSocket就足够了
以上介绍了“ 关于Socket模型 重叠IO 完成例程模型”的问题解答,希望对有需要的网友有所帮助。
本文网址链接:http://www.codes51.com/itwd/3662684.html