您好,欢迎来到[编程问答]网站首页   源码下载   电子书籍   软件下载   专题
当前位置:首页 >> 编程问答 >> Delphi >> 关于Socket模型 重叠IO 完成例程模型

关于Socket模型 重叠IO 完成例程模型

来源:网络整理     时间:2016/8/29 15:24:47     关键词:

关于网友提出的“ 关于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

相关图片

相关文章