2014-06-25 46 views
-1

我有一个服务器和一个客户端(德尔福)。Indy TCP服务器冻结,不知道为什么

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

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

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

这是服务器返回错误: This is the error the server is returning
所以错误似乎是在ADOQuery打开执行SQL的连接,它为什么会只有30只后会执行一个例外?

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

+2

什么阻止你调试呢?什么阻止你自己调查你的想法? –

回答

4

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

TIdTCPClient如果它仍处于打开状态,则在销毁过程中关闭套接字。

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

在这种情况下,你应该:

  1. 给每个客户自己的ADO连接和查询对象。你既可以:

    A.在OnConnect事件创建它们并让它们在TIdContextOnExecute事件中使用内储存,然后释放它们在OnDisconnect eventt。或者根据需要在OnExecute事件中创建并释放它们。

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

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

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

+0

请再次检查问题我添加了我在服务器端得到的错误的屏幕截图 – Craig

相关问题