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

 

在我以前写的文章中,一直说的是如何接收数据。但是对于如何发送数据却一点也没有提到。因为从代码量上来说接收的代码要比发送多很多。今天我就来写一下如何使用IOCP发送数据。

 
function TNetControl.SendSpecifyData(const Socket: TSocket; Data: array of char;
  DataLen: Integer): Boolean;

 
const

 
  DATA_BUFSIZE = 1024;  //这里定义一个发送数据的缓存长度,只要和接收的一直就可以

 
var
  PerIoData: LPPER_IO_OPERATION_DATA ;
  SendBytes, RecvBytes: DWORD;
  Flags: DWORD ;
  LenStr:String;
  SendBuf:array [0..DATA_BUFSIZE] of char;
begin
  try
 //由于粘包的关系,所以在需要发送的数据前面加入4位这次发送数据的长度。(详见我的前一篇文章)

 
 SetArrayLength(DataLen,LenStr) ;
    Fillchar(SendBuf,sizeof(SendBuf),#0);
    strmove(SendBuf,Pointer(LenStr),4);
    strmove(SendBuf+4,Data,DataLen);

 
 //在这里申请一个发送数据的"单IO数据结构"
    PerIoData := LPPER_IO_OPERATION_DATA(GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA)));
    if (PerIoData = nil) then
    begin
      Result:=false;
      exit;
    end;
    ZeroMemory(@PerIoData.Overlapped, sizeof(OVERLAPPED));
    //设置发送标记

 
 PerIoData.BytesRECV := 0;
    PerIoData.DataBuf.len := DataLen+4;
    PerIoData.DataBuf.buf:=@SendBuf;
    PerIoData.BytesSEND := DataLen+4;
    Flags := 0;

 
 //使用WSASend函数将数据发送
    if (WSASend(Socket, @(PerIoData.DataBuf), 1, @SendBytes, 0,@(PerIoData.Overlapped), nil) = SOCKET_ERROR) then
    begin
      if (WSAGetLastError() <> ERROR_IO_PENDING) then
      begin
        //最近在检查代码的时候发现以前这里只是使用Exit来退出是不正确的。这里需要删除申请的单IO数据结构,否子会出现内存泄露。 (2008年3月24日)
        //Exit;
        //表示发送失败,以后也不会有处理在工作者线程处出现。
        if PerIoData <> nil then
        begin
          GlobalFree(DWORD(PerIoData));
        end;
        Result:=false;
        Exit;
      end;
    end;
    Result:=true;
  except
    Result:=false;
  end;
end;
 
 
使用IOCP发送数据的代码就这些,但是这里需要说明一些问题。

 
1:读者一定发送我们在申请了“单IO数据结构”以后并没有对它进行释放。这是因为我们使用的是异步函数WSASend来进行发送数据,只有当我们确定将数据发送出去以后才可以将我们申请的这个结构释放。这就引出了第二个问题。

 
2:如何判断我们发送的数据已经发送。向我以前的文章中所说的“IOCP可以接受来自客户端的数据和自己发送出去的数据”,而区分这个数据是来自客户端还是自己发送出去的区分就是使用PerIoData.BytesRECV 和PerIoData.BytesSEND 如果PerIoData.BytesSEND >0则表示这个数据是自己发送出去的。现在咱们来回顾一下以前的代码,找出释放“单IO数据结构”的地方。

 
在第二篇文章我写了这样的代码。

 
//当我们判断出来接受的数据是我们发送出去的数据的时候,在这里我们清空我们申请的内存空间
else
begin
   GlobalFree(DWORD(PerIoData));
end;

 
这里就是我们释放“单IO数据结构”的地方。

 
到此我已经将整个的IOCP从创建、初始化、接收和发送简单的描述了一下。如果读者根据我写的思路或者代码就可以编写出以后稳定的基于IOCP的网络程序。

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

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

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

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

    DELPHI中完成端口(IOCP)的简单分析(2)   今天我写一下关于DELPHI编写完成端口(IOCP)的工作者线程中的东西.希望各位能提出批评意见.上次我写了关于常见IOCP的代码,对于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. System.IO.File.WriteAllText("log.txt", "dddd");

    System.IO.File.WriteAllText("log.txt", "dddd");

  2. 【Android】解析AccessibilityService(辅助服务)的使用

    辅助功能是Android系统提供的一种服务,派生自Service类.这个服务提供了增强的用户界面,目的是为了帮助残障人士.它一般提供了页面元素查找功能和元素点击功能. 通过辅助功能,开发者可以实现一些 ...

  3. python 执行sql得到字典格式数据

    本文在提供一种方式,实现执行sql语句 返回字典结果集 # 连接数据库,数据库的,这里使用的setting中的默认设置,在这里不做具体的介绍,不懂的可以百度一下 conn = MySQLdb.conn ...

  4. Java基础(四)线程快速了解

    开始整理线程之前,之前有个命令忘记整理了,先整理一下jar命令的使用 Jar包 其实可以理解是java的压缩包方便使用,只要在classpath设置jar路径即可数据库驱动,ssh框架等都是以jar包 ...

  5. ios 适配iOS11&iPhoneX的一些坑

    前阵子项目开发忙成狗,就一直没做iOS11的适配,直到XcodeGM版发布后,我胸有成竹的在iPhoneX上跑起项目,整个人都凉透了...下面总结一下我遇到的坑,不是很全面,日后补充. 导航栏 导航栏 ...

  6. dedecms 5.7sp2 20170405运行PHP7.1的大坑(dedecms PHP7.1)

    今天一个小站用了dedecms最新版,也就是5.7SP220170405版,(见下图) 点进去到下载页面下载,用了UTF8版本的.(见下图) 下载完成后,自己新开发了一套模板,听说PHP7.1性能提升 ...

  7. C# 获取对象 大小 Marshal.SizeOf (sizeof 只能在不安全的上下文中使用)

    C# 能否获取一个对象所占内存的大小? 今日,在项目重构的时候忽然想到一个问题,一个类哪些成员的增加,会影响一个类所占内存的大小?C#有没有办法知道一个对象占多少内存呢? 第一个问题:很快想到是类的非 ...

  8. Logstash安装和使用

    Logstash 是开源的服务器端数据处理管道,能够同时 从多个来源采集数据.转换数据,然后将数据发送到您最喜欢的 “存储库” 中.(我们的存储库当然是 Elasticsearch.) 作用:集中.转 ...

  9. Mock an function to modify partial return value by special arguments on Python

    Mock an function to modify partial return value by special arguments on Python python mock一个带参数的方法,修 ...

  10. miniprogrampatch 提供 watch 和 computed 特性

    推荐一个小程序补丁 github:miniprogrampatch,为你的 Page 和 Component 增加 watch 和 computed 特性. 安装 通过 npm 安装:npm inst ...