DELPHI中完成端口(IOCP)的简单分析(2)

 
今天我写一下关于DELPHI编写完成端口(IOCP)的工作者线程中的东西。希望各位能提出批评意见。
上次我写了关于常见IOCP的代码,对于IOCP来说,接受到客户端发送过来和自己发送出去的数据都是从工作者线程中得到。代码和解释如下:
function ServerWorkerThread(CompletionPortID:Pointer):Integer;stdcall;
begin
   CompletionPort:=THANDLE(CompletionPortID);
   //得到创建线程是传递过来的IOCP
   while(TRUE) do
   begin
        //工作者线程会停止到GetQueuedCompletionStatus函数处,直到接受到数据为止
        if (GetQueuedCompletionStatus(CompletionPort, BytesTransferred,DWORD(PerHandleData), POverlapped(PerIoData), INFINITE) = False) then
        begin
          //当客户端连接断开或者客户端调用closesocket函数的时候,函数GetQueuedCompletionStatus会返回错误。如果我们加入心跳后,在这里就可以来判断套接字是否依然在连接。
          if PerHandleData<>nil then
          begin
            closesocket(PerHandleData.Socket);
            GlobalFree(DWORD(PerHandleData));
          end;
          if PerIoData<>nil then
          begin
            GlobalFree(DWORD(PerIoData));
          end;
          continue;
        end;
        if (BytesTransferred = 0) then
        begin
           //当客户端调用shutdown函数来从容断开的时候,我们可以在这里进行处理。
           if PerHandleData<>nil then
           begin
             TempSc:=PerHandleData.Socket;
             shutdown(PerHandleData.Socket,1);
             closesocket(PerHandleData.Socket);
             GlobalFree(DWORD(PerHandleData));
           end;
           if PerIoData<>nil then
           begin
             GlobalFree(DWORD(PerIoData));
           end;
           continue;
        end;
        //在上一篇中我们说到IOCP可以接受来自客户端的数据和自己发送出去的数据,两种数据的区别在于我们定义的结构成员BytesRECV和BytesSEND的值。所以下面我们来判断数据的来自方向。因为我们发送出去数据的时候我们设置了结构成员BytesSEND。所以如果BytesRECV=0同时BytesSEND=0那么此数据就是我们接受到的客户端数据。(这种区分方法不是唯一的,个人可以有自己的定义方法。只要可以区分开数据来源就可以。)
        if (PerIoData.BytesRECV = 0) and (PerIoData.BytesSEND = 0) then
        begin
           PerIoData.BytesRECV := BytesTransferred;
           PerIoData.BytesSEND := 0;
        end
        else
        begin
           PerIoData.BytesSEND := BytesTransferred;
           PerIoData.BytesRECV := 0;
        end;
        //当是接受来自客户端的数据是,我们进行数据的处理。
        if (PerIoData.BytesRECV > PerIoData.BytesSEND) then
        begin
          PerIoData.DataBuf.buf := PerIoData.Buffer + PerIoData.BytesSEND;
          PerIoData.DataBuf.len := PerIoData.BytesRECV - PerIoData.BytesSEND;
          //这时变量PerIoData.Buffer就是接受到的客户端数据。数据的长度是PerIoData.DataBuf.len 你可以对数据进行相关的处理了。
          //.......
          
          //当我们将数据处理完毕以后,应该将此套接字设置为结束状态,同时初始化和它绑定在一起的数据结构。
          ZeroMemory(@(PerIoData.Overlapped), sizeof(OVERLAPPED));
          PerIoData.BytesRECV := 0;
          Flags := 0;
          ZeroMemory(@(PerIoData.Overlapped), sizeof(OVERLAPPED));
          PerIoData.DataBuf.len := DATA_BUFSIZE;
          ZeroMemory(@PerIoData.Buffer,sizeof(@PerIoData.Buffer));
          PerIoData.DataBuf.buf := @PerIoData.Buffer;
          if (WSARecv(PerHandleData.Socket, @(PerIoData.DataBuf), 1, @RecvBytes, @Flags,@(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
          begin
            if (WSAGetLastError() <> ERROR_IO_PENDING) then
            begin
              if PerHandleData<>nil then
              begin
                TempSc:=PerHandleData.Socket;
                closesocket(PerHandleData.Socket);
                GlobalFree(DWORD(PerHandleData));
              end;
              if PerIoData<>nil then
              begin
                GlobalFree(DWORD(PerIoData));
              end;
              continue;
            end;
          end;
        end
        //当我们判断出来接受的数据是我们发送出去的数据的时候,在这里我们清空我们申请的内存空间
        else
        begin
          GlobalFree(DWORD(PerIoData));
        end;
   end;
end;
到此,工作者线程已经处理完成。接受数据已经没有问题了。下一篇中我将会写出,如何时候IOCP来发送数据代码。今天的代码中应该对PerIoData.BytesRECV > PerIoData.BytesSEND单另解说一下。其实如果按照上面的例子去编写工作者线程,会觉得编写出来的代码会很不稳定,接受到的数据总是有错位的现象。原因是TCP协议中有数据分片的概念,这个以后我会将我处理这个的代码分享给大家。

DELPHI中完成端口(IOCP)的简单分析(2)的更多相关文章

  1. DELPHI中完成端口(IOCP)的简单分析(4)

    DELPHI中完成端口(IOCP)的简单分析(4)   在我以前写的文章中,一直说的是如何接收数据.但是对于如何发送数据却一点也没有提到.因为从代码量上来说接收的代码要比发送多很多.今天我就来写一下如 ...

  2. DELPHI中完成端口(IOCP)的简单分析(3)

    DELPHI中完成端口(IOCP)的简单分析(3)   fxh7622关注4人评论7366人阅读2007-01-17 11:18:24   最近太忙,所以没有机会来写IOCP的后续文章.今天好不容易有 ...

  3. DELPHI中完成端口(IOCP)的简单分析(1)

    DELPHI中完成端口(IOCP)的简单分析(1)   用DELPHI开发网络代码已经有一段时间了! 我发现在网上用VC来实现完成端口(IOCP)的代码很多,但是使用DELPHI来实现的就比较少了.对 ...

  4. java 中 “文件” 和 “流” 的简单分析

    java 中 FIle 和 流的简单分析 File类 简单File 常用方法 创建一个File 对象,检验文件是否存在,若不存在就创建,然后对File的类的这部分操作进行演示,如文件的名称.大小等 / ...

  5. rocketmq中的NettyRemotingClient类的简单分析

    rocketmq中的NettyRemotingClient类的简单分析 Bootstrap handler = this.bootstrap.group(this.eventLoopGroupWork ...

  6. Delphi中Android运行和JNI交互分析

    Androidapi.JNIBridge负责和JNI交互.,既然要交互,那么首先就是需要获得JNI的运行环境,Android本身内置的就有一个Java(Dalvik)虚拟机.所以这个第一步就肯定是要这 ...

  7. 关于Delphi中多线程传递参数的简单问题

    http://bbs.csdn.net/topics/390513469/ unit uThread; interface uses Classes; type Th = class(TThread) ...

  8. 不用注册热键方式在Delphi中实现定义快捷键(又简单又巧妙,但要当前窗体处在激活状态)

    第一步:在要实现快捷键的窗体中更改属性“KeyPreview”为True:第二步:在要实现快捷键的窗体中的OnKeyPress事件中填入一个过程名称(在Object Inspector中),填写好后回 ...

  9. jQuery中样式和属性模块简单分析

    1.行内样式操作 目标:扩展框架实现行内样式的增删改查 1.1 创建 css 方法 目标:实现单个样式或者多个样式的操作 1.1.1 css方法 -获取样式 注意:使用 style 属性只能获取行内样 ...

随机推荐

  1. iOS实现pdf文件预览,上下翻页、缩放,读取pdf目录

    最近有个朋友想做一个pdf预览,要求能够上下滑动翻页.带缩放.目录跳转功能. 因为之前我只做过简单的预览,那时直接用uiwebview实现的,这次找了下资料,发现一个比较好的库. 其原理实现: 自定义 ...

  2. .net core 2.0+superui +Dapper.SimpleCRUD+mysql+NLog

    **_ .net core 2.0+superui +Dapper.SimpleCRUD+mysql+NLog _** 前端框架 superui http://www.supermgr.cn/ 1.组 ...

  3. 一次python 内存泄漏解决过程

    最近工作中慢慢开始用python协程相关的东西,所以用到了一些相关模块,如aiohttp, aiomysql, aioredis等,用的过程中也碰到的很多问题,这里整理了一次内存泄漏的问题 通常我们写 ...

  4. 关于web项目创建后WEB-INF下面没有出现web.xml的解决方法

    提供两种解决方案: 第一种:创建完项目后,需要手动创建出web.xml 第一步:选取创建的项目名称右击 第二步:eclipse的同学找到 java EE Tools 中的 下图画圈部分.  MyEcl ...

  5. [CI]jenkins安装&插件管理&java-helloworld之旅

    持续集成概述 没有持续集成时的情况 持续集成最佳实战 维护一个单一的代码库 使构建自动化 执行测试是构建的一部分 集成日志及历史记录 使用统一的依赖包管理库 每天至少集成一次 jenkins实现持续集 ...

  6. Linux将yum源设置为阿里云的镜像源

    第一步:备份原有镜像源 mv /etc/yum.repo.d/Centos-Base.repo /etc/yum.repo.d/Centos-Base.repo.bak 第二步:下载阿里云的镜像源 w ...

  7. (转)java术语(PO/POJO/VO/BO/DAO/DTO)

    转自:http://blog.csdn.net/gaoyunpeng/article/details/2093211 PO(persistant object) 持久对象在o/r 映射的时候出现的概念 ...

  8. fastDFS 命令笔记

    端口开放 这是命令运行的前提 iptables -I INPUT -p tcp -m state –state NEW -m tcp –dport 22 -j ACCEPT iptables -I I ...

  9. 梯度下降(gradient descent)算法简介

    梯度下降法是一个最优化算法,通常也称为最速下降法.最速下降法是求解无约束优化问题最简单和最古老的方法之一,虽然现在已经不具有实用性,但是许多有效算法都是以它为基础进行改进和修正而得到的.最速下降法是用 ...

  10. Linux下配置环境变量—— .bashrc 和 /etc/profile

    转载:https://blog.csdn.net/sun8112133/article/details/79901527 首先简单说一下什么是环境变量?环境变量简单的说就是当前环境下的参数或者变量.如 ...