【问题标题】:Indy TCP Server Freezes, no idea whyIndy TCP 服务器冻结,不知道为什么
【发布时间】:2014-06-25 19:23:21
【问题描述】:

我有一个服务器和一个客户端 (Delphi)。

客户端获取登录详细信息然后连接到服务器将它们发送到服务器进行验证,服务器接收到数据验证它然后返回给定数据是否正确。

如果数据正确,客户端会继续下一个窗口,在该窗口中将一些数据输入到相应的字段中,然后将数据发送到服务器,当服务器接收到数据时,它会存储它,然后回复客户端它存储的数据它成功了。当客户端被通知数据已成功存储时,它会显示一条消息通知用户,然后终止。

在测试时,客户端在四台不同的计算机上运行,​​(每台计算机将打开和关闭客户端大约 6 次)服务器突然停止回复客户端(客户端显示消息“连接正常关闭”)

这是服务器返回的错误:
所以错误似乎是当ADOQuery打开连接执行SQL时,为什么只有执行30次才会导致异常?

任何关于我的问题的建议,因为我不知道它可能是什么。 谢谢你的帮助:)

【问题讨论】:

  • 是什么阻止你调试这个?是什么阻止了你自己研究你的想法?

标签: delphi delphi-7 ado indy


【解决方案1】:

如果客户端收到“连接正常关闭”错误,这意味着服务器在服务器端关闭了该客户端的连接。如果您的服务器代码没有明确地这样做,那么通常意味着在服务器的事件处理程序之一中引发了未捕获的异常,这将导致服务器关闭套接字(如果在 OnConnect 事件之后和之前引发了异常OnDisconnect 事件,OnDisconnect 在套接字关闭之前触发)。 TIdTCPServer 有一个 OnException 事件来报告这种情况。

TIdTCPClient 在销毁期间关闭套接字(如果它仍然打开)。

更新TIdTCPServer 是一个多线程组件。每个客户端连接都在自己的线程中运行。 ADO 使用与创建它们的线程绑定的单元线程 COM 对象,并且只能在该线程上下文中使用,除非使用 CoMarshalInterThreadInterfaceInStream() + CoGetInterfaceAndReleaseStream()IGlobalInterfaceTable 接口跨线程边界封送。

在这种情况下,您应该:

  1. 为每个客户端提供自己的 ADO 连接和查询对象。你可以:

    A.在OnConnect 事件中创建它们并将它们存储在TIdContext 中以在OnExecute 事件中使用,然后在OnDisconnect 事件中释放它们。或者只是根据需要在OnExecute 事件中创建和释放它们。

    B.从TIdThreadWithTask 派生一个新类并覆盖其虚拟BeforeExecute()AfterExecute() 方法以创建和释放ADO 对象,然后将TIdSchedulerOfThread... 组件之一分配给TIdTCPServer.Scheduler 属性并将您的线程类分配给TIdSchedulerOfThread.ThreadClass 属性。然后,在服务器事件中,您可以使用TMyThreadClass(TIdYarnOfThread(TIdContext.Yarn).Thread) 访问调用线程的 ADO 对象。

  2. 创建一个单独的 ADO 对象池。当客户端需要访问数据库时,让它将适当的 ADO 对象编组到调用线程的上下文中,然后在完成后将对象放回池中。

无论哪种方式,由于 ADO 是基于 COM 的,不要忘记在 OnConnectOnDisconnect 事件中为需要访问 ADO 对象的每个客户端线程调用 CoInitialize/Ex()CoUnintialize(),或者在TIdThreadWithTask.BeforeExecute()TIdThreadWithTask.AfterExecute() 方法中。

【讨论】:

  • 请再次检查问题我添加了我在服务器端遇到的错误的屏幕截图
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 2020-02-20
  • 2012-12-21
  • 1970-01-01
  • 2016-07-02
相关资源
最近更新 更多