首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

探索DIOCP-V5:专业人士的技术解读与应用

写在前面的话

这篇文章的内容是关于 DIOCP-v5 项目使用的一个入门文章,至于为什么更新这个的入门,最近在鼓捣传奇引擎的项目,发现项目的网络组件分这么几种情况,JSocket、DIOCP-V5、自己封装的 IOCP

据说 JSocket 实现的是轮询模型,其支持并发的次数很低,代码我没看,因为觉得没必要。如果要我选的话我肯定不会选择这个模型,而是在 Windows 系统上最高效的模型 IOCP(相当于 Linux 的 EPOLL)

在很早之前我甚至不知道服务器有 Windows 版本,一直到接触到网络安全(我的工作经历中曾经有一段时间是讲网络安全),我才知道 Windows 也有服务器版本,而传奇引擎很不巧的是部署在 Windows 上

其次是 JSocket,先不说低效的问题,哪怕是现在的高版本 Delphi 的 IDE 都很难找到一个可以适配的版本。所以继上一篇 Delphi-Corss-Socket 之后又出现了这篇文章

项目地址:

https://github.com/ymofen/diocp-v5

我不知道现在这个时间节点还会有多少人会看这篇文章,毕竟现在 AI 大行其道,什么东西不会了直接问 AI 基本上都会有答案

DIOCP-V5 的目录结构

我觉得还是有必要说一下目录结构的,理由嘛,网络上不知道有没有类似的入门教程的文章(至少我没找到)。

E:\MIR\MIR\DIOCP-V5

  ├─doc     这个目录很明显存放的是说明档,一般情况下开源项目都会有这个

  ├─samples 这里其实存放的就是官方的示例代码,而我的入门其实也是从这里开始的

  └─source  这里存放的就是 DIOCP 的源码,需要我们在项目中引入的目录

这里需要特别说明一下,DIOCP 貌似不挑 Delphi IDE 的版本,因为我在 Delphi2007 和 Delphi XE12.2 上分别可以使用

如果说有什么缺点的话,就是和 Delphi-Corss-Socket 相比的话代码可能没那么明确。这个观点是在直播的适合有一个网友说的,其实对我来说都差不多,反正都不会

DIOCP-V5 的快速上手

和之前的项目一样,都需要一个可以快速上手的项目,但是很可惜官方的案例中好像没有这种项目

uses

  diocp_tcp_server, utils_safeLogger,    utils_BufferPool, utils_fileWriter, utils_async; //首先是包的引入

//其次就是指定服务的事件处理函数,具体的函数实现我就不写了,只是需要注意的是这些函数必须放在类中

procedure TForm2.FormCreate(Sender: TObject);

begin

FTcpServer := TDiocpTcpServer.Create(Self);

FTcpServer.Port                  :=10086;

FTcpServer.DefaultListenAddress  := '127.0.0.1';

FTcpServer.Name                  := 'iocpSVR';

FTcpServer.OnDataReceived        := OnRecvBuffer;

FTcpServer.OnContextAccept       := OnAccept;

FTcpServer.OnContextConnected    := OnContextConnected ;

FTcpServer.OnSendBufferCompleted := OnSendBufferCompleted;

FTcpServer.OnContextDisconnected := OnDisconnected;

end;

//重点说一下这个函数,里面有两个参数很重要,一个是指针,另一个是长度

procedure TForm2.OnRecvBuffer(pvClientContext: TIocpClientContext; buf: Pointer; len: cardinal; errCode: Integer);

var

receivedMessage: AnsiString;

begin

// 检查是否没有错误

if errCode = 0thenbegin

  // 将接收到的字节流转换为字符串

  SetLength(receivedMessage, len);     // 设置字符串的长度为接收到的数据长度

  Move(buf^, receivedMessage[1], len); // 从缓冲区复制数据到字符串中

  // 显示接收到的消息

  Memo1.Lines.add('收到的消息:: ' + receivedMessage);

  //提交一个发送的请求

  pvClientContext.PostWSASendRequest(buf,len);

endelsebegin

  // 处理错误:可以根据错误码进行相应的处理

  ShowMessage('Error occurred while receiving data. Error code: ' + IntToStr(errCode));

end;

end;

这里有一个问题,就是为什么接收的是指针,而不是像 JSocket 一样发送和接收可以直接是字符串。我猜的原因可能是发送的数据除了普通文本之外还有二进制数据

下面是客户端程序

uses

  diocp_tcp_client,utils_safeLogger, ComCtrls, diocp_sockets, ExtCtrls, utils_async,

  diocp_coder_tcpClient, utils_BufferPool, utils_fileWriter, diocp_tcp_blockClient, Registry,

  utils_strings, diocp_task;

constructor TRunGate.Create(Memo: TMemo);

begin

try

  //游戏客户端配置

  ClientSocket := TDiocpTcpClient.Create(nil);

  ClientSocket.OnContextConnected    := ClientSocketConnect;           //建立连接

  ClientSocket.OnContextDisconnected := ClientSocketDisconnect;        //关闭连接

  ClientSocket.OnReceivedBuffer      := ClientSocketRead;

  //M2 连接配置

  DiocpContext := TDiocpExRemoteContext(ClientSocket.Add);

  DiocpContext.Host := '127.0.0.1';

  DiocpContext.Port := 10086;

  ClientSocket.open;

  ClientSocket.DisableAutoConnect := True;

  DiocpContext.Connect;

except

  on E: Exception do

    //AddMainLogMsg(E.Message, 1);

end;

end;

//这里需要说明一下,当时是为了一个传世的单子,这里是测试代码,开启了一个线程,但是即便是普通的按钮点击事件也是一样的

procedure TWorkThread.Execute;

var

Content: Pointer;

SendMsg:string;

Index:Integer;

begin

while True do

begin

    SendMsg:='我是祖国的花朵'+IntToStr(Index);

    Self.RunGate.DiocpContext.PostWSASendRequest(PChar(SendMsg),Length(SendMsg));

    Sleep(1000);

    Inc(Index);

  end;

end;

end;

写在最后的话

我曾经好奇过为什么会有 JSocket 这种东西,后来想想其实没那么难理解,怎么说呢,我觉得是两个原因

• 传奇引擎的架构问题,它存在网关,而网关的一个很重要的功能就是缓存消息,我看到的代码都是由一个 TList 作为消息的临时存放,然后再慢慢的把消息从列表中转发给 M2

• 第二个其实应该是和时代有关系,传奇盛行的年代可能 IOCP 还没出现

最后,其实无论选择什么网络模型,套用 GM 的话,能跑起来的引擎就是好引擎。我这里说的只是针对网络的学习。

还有一件事差点忘了说,第二季的视频不是停更了,是因为我遇到了问题,第 1 个是屏幕截屏的算法,第 2 个是屏幕截屏之后怎么压缩发送数据。如果哪位同道知道的话还望不吝赐教

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OtJrudn06IzYNxZO4WpkVHqA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
首页
学习
活动
专区
圈层
工具