工作者线程是发送和接收数据的主要部分。没有这部分代码,是无法实现网络通信的。今天我就来讲一下我写的工作者线程是如何实现的。
首先是工作者线程的创建和销毁。
constructor TWorkThread.Create(Parent: TIOEvents);
begin
  inherited Create(False);
  FParent:=Parent;
end;
我写工作者线程的时候,是将父类(TIOEvents)通过参数传递进来,这样写是为了以后的使用方便。
destructor TWorkThread.Destroy;
begin
  inherited;
end;
以下是工作者线程的主要代码。
procedure TWorkThread.Execute;
var
  Index:Integer;
  ne:TWSANETWORKEVENTS;
begin
  while not Terminated do
  begin
    Index := WSAWaitForMultipleEvents(FParent.FEventNums,@FParent.FEventArray[0],FALSE,WSA_INFINITE,FALSE);
    if Index = -1 then
    begin
      //得到-1应该是需要断开
      Exit;
    end;
    //得到事件对应的数组下标
    Index := Index - WSA_WAIT_EVENT_0;
    //重置事件
    WSAResetEvent(FParent.FEventArray[Index]);
    if (Index = WSA_WAIT_FAILED) or (Index = WSA_WAIT_TIMEOUT) or (Index = WSA_INVALID_PARAMETER) or (WSA_INVALID_HANDLE = Index) or (WSANOTINITIALISED = Index) then
    begin
      Continue;
    end;
    //开始得到网络事件
    if WSAEnumNetworkEvents(FParent.FSocketArray[Index],FParent.FEventArray[Index],@ne) <> INVALID_SOCKET then
    begin
      case ne.lNetworkEvents of
        FD_READ:  SocketRead;   //接收数据
        FD_WRITE: SocketWrite;  //发送数据
        FD_CLOSE: SocketClose;  //连接关闭
      end;
    end;
  end;
end;
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
由于我在函数WSAWaitForMultipleEvents中使用了参数WSA_INFINITE,这样程序会等在这里一直到套接字上有事件触发。事件触发以后我使用函数WSAResetEvent重置了事件。并使用函数WSAEnumNetworkEvents确定出触发了什么事件。根据不同的事件我调用不同的处理方法。
对于连接关闭事件我的实现是:
procedure TWorkThread.SocketClose;
begin
  if Assigned(FParent.FOnDisConnect) then
  begin
    FParent.OnDisConnect;
  end;
  //服务端断开
  FParent.ClearBuffer;
  Destroy;
end;
对于接收到数据事件,我的实现是:
procedure TWorkThread.SocketRead;
var
  BytesTransferred,dwFlags: DWORD;
  iData:Pchar;
begin
  BytesTransferred:=0;
  FParent.PostRecv;
  if WSAGetOverlappedResult(FParent.FSocket, @FParent.FRecvIOData.Overlapped, @BytesTransferred, FALSE, @dwFlags) then
  begin
    if BytesTransferred = 0 then
    begin
      Exit;
    end;
    FParent.FRecvIOData.BufferLen:=BytesTransferred;
    GetMem(iData,FParent.FRecvIOData.BufferLen);
    StrMove(iData,@FParent.FRecvIOData.Buffer,FParent.FRecvIOData.BufferLen);
    if Assigned(FParent.FOnRecive) then
    begin
      FParent.FOnRecive(iData,FParent.FRecvIOData.BufferLen);
    end;
    FreeMem(iData);
  end;
end;
我调用函数WSAGetOverlappedResult用来得到接收到的数据信息。并产生一个接收数据事件。
对于发送数据事件,我的处理方法是:
procedure TWorkThread.SocketWrite;
begin
  Dec(FParent.FTotalCount);
  if Assigned(FParent.FFirstNode) then
  begin
    if not FParent.PostSend then
    begin
      closesocket(FParent.FSocket);
    end;
  end
  else
  begin
    FParent.FSending:=false;
  end;
end;
继续投递一个PostSend。来继续发送,发送队列中的数据。至此,Event模型编写客户端通信的主要代码就已经全部写完了,我的代码一定会有一些问题,希望大家看了以后能指出错误来,好让大家一起进步。
initialization
  begin
    WSAStatupSocket;
  end;
finalization
  begin
    WSACleanupSocket;
  end;
end.

转载于:https://blog.51cto.com/fxh7622/166942

Delphi编写事件模型客户端(3)相关推荐

  1. Delphi编写事件模型客户端(2)

    上次写了事件模型类的定义,今天我来写一写如何实现这个类. 首先的两个函数我想稍微了解网络编程的人都会清楚.<?xml:namespace prefix = o ns = "urn:sc ...

  2. 回调函数与Delphi的事件模型

    回调函数: 回调函数是这样一种机制:调用者在初始化一个对象(这里的对象是泛指,包括OOP中的对象.全局函数等)时,将一些参数传递给对象,同时将一个调用者可以访问的函数地址传递给该对象.这个函数就是调用 ...

  3. Delphi动态事件

    Delphi动态事件深入分析 核心提示:本实验证明了在类中方法的调用时候,所有的方法都隐含了一个Self参数,并且该参数作为对象方法的第一个参数传递... 首先做一个空窗体,放入一Button. 在i ...

  4. spring 事件模型_Spring–设计领域模型和服务层

    spring 事件模型 我们将为时间表管理构建应用程序. 因此,让我们首先考虑一些用例和实体. 让我用几个项目符号写它们: 任务由经理分配给员工. 一项任务可以分配给许多员工. 员工将他在某些任务上工 ...

  5. 事件库之Redis自己的事件模型-ae

    2019独角兽企业重金招聘Python工程师标准>>> #Redis自己的事件模型 ae ##1.Redis的事件模型库 大家到网上Google"Redis libeven ...

  6. 国内首部HTML5技术之拉米牌游戏项目实战(涉及智能AI+HTML5图形+HTML5事件模型+网络通讯)...

    课程学习地址:http://***/goods.php?id=186 课程适合人群:       本课程适合Java人群.ASP.NET人群.美工及各类前端设计者学习,学员只需要懂得基本的程序设计思想 ...

  7. Redis | 第6章 事件与客户端《Redis设计与实现》

    第6章 事件与客户端 前言 1. 事件 1.1 文件事件 1.1.1 I/O 多路复用程序的实现 1.1.2 事件类型与 API 1.1.3 文件事件的处理器 1.2 时间事件 1.2.1 API 1 ...

  8. nginx进程模型,事件模型

    众所周知,nginx性能高,而nginx的高性能与其架构是分不开的.那么nginx究竟是怎么样的呢?这一节我们先来初识一下nginx框架吧. nginx在启动后,在unix系统中会以daemon的方式 ...

  9. redis的事件模型详解(结合Reactor设计模式)

    文章基于redis-4.0.1源码详细介绍一下redis的事件模型. 一.redis事件模型概览 redis是一个事件驱动的服务程序,在redis的服务程序中存在两种类型的事件,分别是文件事件和时间事 ...

  10. Java图形用户界面3—AWT事件模型

    我们编写图形用户界面并不只是为了显示,我们是为了借助图形用户界面来完成我们需要的工作.这就需要程序为我们的动作比如点击按钮,做出响应然后完成我们的工作.在这里我们就用到了事件. 在Java事件模型中, ...

最新文章

  1. (十二)企业级java springcloud b2bc商城系统开源源码二次开发-断路器监控(Hystrix Dashboard)...
  2. 雷达篇(九)雷达中的“快采样”和“慢采样”
  3. CSP认证201509-2 日期计算[C++题解]:枚举、模拟
  4. 数组中有一个数字出现的次数超过数组长度的一半
  5. Hadoop IO 文件压缩 序列化
  6. 【DP】数的划分(ybtoj DP-1-3)
  7. 从入门到精通:卷积神经网络初学者指南
  8. 【语言处理与Python】5.7如何确定一个词的分类
  9. 牛腩新闻发布系统—发布网站
  10. Linux中chmod用法
  11. Unity PlayerPrefs 游戏存档
  12. 使用C#存储数据时excel有Microsoft切换到了wps时的引用
  13. 嵌入式软件工程师岗位要求
  14. 方舟服务器维护为什么要藏好,方舟生存进化芯片藏哪儿好
  15. html 圆角矩形,圆角矩形
  16. 公众号开发素材管理效果演示-微信开发素材管理1
  17. google输入法PK搜狗输入法
  18. [bzoj5020][THUWC 2017]在美妙的数学王国中畅游
  19. RAM/ROM存储器的设计
  20. 高并发处理与解决方案

热门文章

  1. break与continue关键字的使用
  2. [转][Err] 1452 - Cannot add or update a child row: a foreign key constraint fail
  3. python的条件(三元)运算符——实现b? x: y
  4. b树删除节点每次只能删一个吗_【面试索引】BTree、B+Tree、红黑树、B*Tree数据结构...
  5. 2017-2018-2 PDE 讨论班
  6. Hibernate(5)—— 联合主键 、一对一关联关系映射(xml和注解) 和 领域驱动设计...
  7. internet与Internet的区别
  8. java 通过网络 ntp 获取网络时间
  9. HTML 学习笔记一
  10. 让Android的输入框与文本框带滚动条ScrollView