【DIOCP-说明书】常见问题(FAQ)持续更新

1.diocp-v5使用在哪里可以得到帮助
http://www.diocp.org/?page_id=159
  可以浏览官方社区的一些基础说明,该文档会陆续进行整理。

 

2.diocp-v5怎么样编译DEMO 
  <<关于DEMO的编译>>
http://www.diocp.org/?p=16
2.1
Q:在编译DiocpV5DEMO是编译不通过
A:你编译DEMO的时候,把diocpv5\source加入到路径就好
  不要把所有Source下的文件添加到工程,因为有一些文件是给android/ios平台用的当然不能在windows下面编译,
  例如:diocp.core.rawPosixSocket.pas

 

3.服务端避免不了和多线程打交道,请先好好熟悉多线程的基础知识和注意实现。下面有多线程的一些文章,请认真看看。
http://blog.qdac.cc/?p=890

 

 

Q:服务端在线信息显示为何与实际有差异?
Q:服务端许多死链接都显示在线?
A:DIOCP默认关闭了心跳。所以会造成很多死链接,仍然显示在线,详细原因点击查看该文章:http://www.diocp.org/?p=189
(【DIOCP3-说明书】关于服务端的KeepAlive属性(心跳))

 

Q: 在Diocp中我需要另外开线程去处理逻辑吗?
A: 在编码层(TDiocpCoderTcpServer), 逻辑处理事件(OnContextAction), 是由DiocpTask/Qworker(编译开关(QDAC_QWorker)可以进行切换)驱动的,和底层的通信线程是不相干扰。所以在编码层不需要使用另外的线程池,来处理逻辑。

 

Q: 同一个连接的OnContextAction会同时被多个线程触发吗?
A:编码层的OnContextAction是排队处理的,底层接收到数据后交由注册的解码器进行解码, 解码成功后,放到任务队列,然后依次触发OnContextAction,所以同一个连接的OnContextAction同时只会有一个线程调用。

 

Q: Diocp的断开日志
A: Diocp在DEBUG模式下面会记录详细的日志。会记录每个连接断开的原因。如下
   1> xxxx:[2824]投递发送数据请求时出现了错误。错误代码:10054
     说明: 这种日志在发送数据的时候系统返回了错误代码,可以根据错误代码(如10054),查询到相应的错误信息。
   2> xxxx: [720]响应接收请求时出现了错误。错误代码:64!
     说明:这种日志在响应接收请求时系统返回的错误,根据错误代码查询响应的信息。
   3> xxxx: [704]接收到0字节的数据,该连接将断开!
     说明: 服务端接收到长度为0字节的数据,认为对方关闭了连接。服务端相应的会释放连接触发OnDiscconected函数。
   4> xxxx :[812]执行[CheckNextSendRequest::lvRequest.ExecuteSend]失败: 处理投递发送请求数据包时,发现异步关闭请求(Request.Tag = -1)。进行关闭处理!
     说明: 这种日志一般在服务端投递了异步关闭请求(PostWSAClose)时,会出现该日志。
   上面列举的日志都是正常的,DIOCP只是记录详细情况,以便出现问题时能有据可查,请勿惊慌。
   * 中括号[]中的数字是连接对应的SocketHandle,是连接的套接字句柄。

   MSDN上面错误代码说明:

      https://msdn.microsoft.com/en-us/library/ms740668.aspx 

      https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

 

Q: Diocp如何关闭日志记录。
A: Diocp在DEBUG模式会记录详细日志。可以把DEBUG模式关闭
   D2007工程为例: Project->Options->Directories/Conditionals->Conditional defines 中把DEBUG删除

DX10下面WSASocket阻塞的情况

今天帮群友调程序,说是程序会卡在WSASocket这一句。看CallStack

 

大概的流程是这样的

Application.Run –> LoadLibrary(A.dll, 带包bpl)->diocp.socket.utils( 初始化单元) –> loadIocpExFunction->WSASocket(阻塞了)

 

后来在主程序中引用diocp.socket.utils单元,使得初始化WSASocket提前到EXE中完成,一切正常

【被C折腾系列】用C调DIOCP编码客户端通信

前几天有个朋友,说他们公司做手游,服务端用的DIOCP3里面做文件服务器,客户端用cocos-x,在调试与diocp通信时老是失败!

 

于是,我下载了一个Codeblocks经过几个小时的折腾,终于折腾出来了,把其中的一些心酸记录下,以便以后查阅。

 

1.windows下面使用socket的一些函数时,需要设置工程的选项或者工具的编译选项

[project –> build options]->[linker settings]或者[setting]->[complier]->Linker settings]中添加

F:\Tools\C\CodeBlocks\MinGW\lib\*.a 到 [link libraries]中

要不然会出现编译错误

undefined reference to `WSAStartup@8′

 

2.关于c中的extern和static

  百度上面有比较多的解释,

  extern 表示修饰的函数或者变量是从其他文件中引用。(extern告诉编译器这个变量或者函数在其他文件里已经被定义了)

  static 表示修饰的函数或者变量只能在本文件中使用。static还可以修饰局部变量,表示局部变量在退出函数后,该变量不可用,但是再次进入到函数时,该变量会保存之前的值。

 

下面为调试的截图(该代码放在目录diocp-v5\samples\StreamCoderDEMO\c_codeblocks编写)

上面截图说明与服务器进行了一次通信,服务器接收特定的编码格式(Flag + CheckValue + datalen + data)

发送过去后,服务端会进行编码原样返回。

 

总结:

    接触一门其他语言,需要多去写代码,只有在写的过程当中才会去碰到问题,解决问题,积累被坑的经验。思路和想法有了,剩下的就是多被坑点就好了

【DIOCP3-说明书】DIOCP3的输出日志

DIOCP3除了有详细的监控面板之外,还有详细的输出日志,当然需要打开日志编译开关!

在工程选项加入DEBUG编译指令,这样在运行中就可以看到DIOCP3的运行详细日志

日志输出在EXE相同目录的LOG文件夹下面。

 

日志说明:

8276_iocpSVR_2015010712.log

8276      是进程ID

iocpSVR是程序中iocpTcpSERVER的名字

2015010712 日志文件生成时间

 

12:30:24:318[message][PID:8276,ThreadID:5520]:[756]接收到0字节的数据,该连接将断开!

PID是进程ID

ThreadID: 工作线程ID

756 套接字

收到一个0字节长度的数据,diocp认为对方已经断开,diocp将关闭套接字对应的连接。

发生在响应WSARecv的事件中。

 

12:37:45:764[message][PID:8276,ThreadID:5520]:[760]响应接收请求时发现IOCP服务关闭

IOCP服务已经关闭, 一般发生在程序关闭,IOCP服务停止的时候,有客户端进行了连接的时候

发生在响应WSARecv的事件中。

 

12:37:45:764[message][PID:8276,ThreadID:5520]:[760]投递发送数据请求时出现了错误。错误代码:10038

在进行发送数据时出现的异常,在执行底层API时出现的异常,错误代码是系统给出的,可以百度,或者进入CMD运行

net helpmsg 10038 查看对应的错误原因。

错误代码121:  信号灯超时已到

一般发生情况,iocpTcpServer打开了KeepAlive,建议关闭KeepAlive自己进行心跳处理。

 

【DIOCP应用案例】-案例2(无毒公主)

案例2<无毒公主>

服务端应用场景:

金融行业交易行情、交易控制指令发布推送服务器。主要是要稳定和快速,对负载要求不高。日常在线20个左右。服务器和客户端都用的diocp实现的iocp异步模式。由于是金融类的应用,对稳定性和推送实时性有非常高的要求(关键时候如果指令延时长了,就会损失真金白银),而一路跟着diocp1走到现在diocp3稳定一年多了 ,各方面的表现完全满足需求。

公司名称:

某金融投资公司

DIOCP版本:

从diocp1到DIOCP3 <自定义的编码器>

QQ昵称:

五毒公主(782834)

建议与问题:

我现在这个还只是一个非常小规模的应用,但是有不同的客户端(指令控制端、管理员端、交易终端)会登录到系统,在不同的客户端多了以后 协议就会多很多。 现在是在在一个编码解码器上按命令字来区分再进行业务层的解析。 虽然能满足需求。但是总觉得 如果要做非常庞大和复杂的系统的话 ,协议的管理将非常麻烦。 所以觉得如果可以一个服务器开放多个端口,每个端口有自己的在线列表,不同的客户端登录到不同的端口、应用不同的编码解码器,同时又能统一管理(应为不同的客户端之前需要数据交、转发)这样就是极好的。

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP应用案例】-案例1(Tiger)

2014101153544361

DIOCP是Delphi下进行IOCP服务端通讯开发的一个非常好的开源框架,稳定、高效并且使用起来十分简单。 自己两个多月之前因为需要使用Delphi开发一个TCP服务端,当时也是到处爬文,希望找到一个稳定且好用的IOCP开源框架,整整一周的时间,看了很多,也对比了很多,最后选择了DIOCP,现在服务器端正式版本已经上线运行了36天的时间了,所有运行一切稳定,无论是CPU占用、内存使用还是通信稳定性,DIOCP的表现真的没有让我失望,表现得非常优秀。

服务器环境:
OS:Windows Server 2003
CPU:Intel 双核      内存:2G
网络带宽:5M
网络类型:BGP
实际性能数据:
程序用户同时在线数:1200 – 1300之间   峰值:1511(此峰值为真实用户同时在线数,不是理论性能峰值,目前的用户数只有这些,自己测试的时候,连接数测试过5K,也同样运行稳定)。
服务器端运行到发文时已经36天多了,内存峰值也只有76M,CPU占用一直都稳定在10%以下,应该说各项指标都非常的好,非常满意。

QQ:
Tiger

 

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP知识库】连接上下文TIocpClientContext

【概述】

     该类管理远程连接,每一个远程连接会对应一个该类的实例,开发时可以通过继承该类,扩展属性,可以存储更多的连接信息,可以重写OnRecvBuffer方法进行数据逻辑的处理

 

【字段/属性说明】

  • property RemoteAddr: String read FRemoteAddr;

说明:远程连接IP。

 

  • property RemotePort: Integer read FRemotePort;

说明:远程连接端口。

 

  • property SocketHandle: TSocket read FSocketHandle;

说明:连接套接字.

 

【方法说明】

  • procedure DoCleanUp;virtual;

说明: 该方法从对象池中获取一个对象时(TIocpTcpServer.getClientContext)执行该方法,进行相关资源的清理,在该实例不再需要,放回到连接池时(TIocpTcpServer.releaseClientContext)也会执行该方法,该方法同时只会一个线程访问和执行。

 

  • procedure PostNextSendRequest; virutal;

说明:该方法在发送请求得到响应完成并成功(TIocpSendRequest.HandleResponse),会再次调用该方法可以进行下一个请求的发送,如果响应中发现GetLastError不为0或者服务关闭已经停止则不会执行该方法

 

  • procedure OnRecvBuffer(buf: Pointer; len: Cardinal; ErrCode: WORD); virtual;

说明:如果接收到远程数据时会触发该函数的执行,该方法在响应投递的接收数据的请求(TIocpRecvRequest.HandleResponse)中调用,如果响应中发现GetLastError不为0或者服务关闭已经停止则不会执行该方法。

 

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP知识库】-粘包的处理

什么是粘包:

   第一次发送  12345, 第二次发送abcde, 底层socket可能会一次性进行发送12345abcde,或者对方可能一次性进行了接收,那接收的时候,你可能想分两次接收才对,第一次接受到12345, 第二次想接收abcde,但是事与愿违,一次就接收完了,这就是粘包的问题。需要自己处理。

 

怎么样处理粘包:

  常见的方法是在包数据的前面加长度比如我先发送一个字节代表长度5 然后再发数据包12345, 这样接收的时候,先读数据包长度,然后再获取包的数据,这样就可以处理粘包问题了。

diocp3的StreamCoder,可以让你直接发送TStream对象,不需要处理粘包的问题。接收到的数据对象就是一个TStream对象

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

[DIOCP3-说明书] 关于DEMO的编译

总有些朋友问我,关于DEMO编译的一些问题,每次都回答大概都差不多,我想还是写篇说明书给大家,关于DEMO编译的步骤。

【环境设定】

1.将DIOCP3\source路径添加到Delphi的搜索路径,[tool->options->Environment Options->Delphi Options –> Libaray –>Libaray Path]

2.打开samples\下面的工程可以进行编译

【常见问题】

1.XE2以上版本,有时候提示一些vcl的单元找不到。

image

解决方法:

工程添加vcl域

image

2. XE2以下版本提示找不到System.actions;

image

解决方法

直接删除即可(一些DEMO在XE5和XE6上面完成的,这个是自动添加的,低版本没有,可以直接删除)

3. D7 下面提示, Application.MainFormOnTaskbar := True;编译不过去

image

解决方法:

直接删除即可,D7不认识这段代码,这是2007以上版本自动生成的。