我有一个服务器和一个客户端(Delphi)。
客户端获取登录详细信息然后连接到服务器将它们发送到要验证的服务器,服务器接收数据验证它然后返回给定数据是否正确。
如果数据正确,客户端会继续到下一个窗口,在那里他们将一些数据输入到相应的字段中,然后将数据发送到服务器,当服务器收到它存储的数据时,然后回复客户端它存储的数据它成功了。当客户端被通知数据已成功存储时,它会显示一条消息,通知用户然后终止。
在对此进行测试时,客户端在四台不同的计算机上运行,(每台计算机将打开和关闭客户端大约6次)服务器突然停止回复客户端(客户端显示消息说" Connection正常关闭& #34)
这是服务器返回的错误:
因此,当ADOQuery打开连接以执行SQL时,错误似乎是,为什么它只会在执行30之后导致异常?
对我的问题有什么建议,因为我不知道它可能是什么。 谢谢你的帮助:)
答案 0 :(得分:4)
如果客户收到" Connection正常关闭"错误,这意味着服务器关闭了客户端在服务器端的连接。如果您的服务器代码没有明确地这样做,那么它通常意味着在其中一个服务器的事件处理程序中引发了未捕获的异常,这将导致服务器关闭套接字(如果在{{之后引发异常)事件在OnConnect
事件之前,OnDisconnect
在套接字关闭之前被触发)。 OnDisconnect
有一个TIdTCPServer
事件来报告该情况。
OnException
在破坏期间关闭套接字,如果它仍处于打开状态。
更新:TIdTCPClient
是一个多线程组件。每个客户端连接都在自己的线程中运行。 ADO使用与创建它们的线程绑定的单元线程COM对象,并且只能在该线程上下文中使用,除非使用CoMarshalInterThreadInterfaceInStream() + CoGetInterfaceAndReleaseStream()或{{3}跨越线程边界封送} interface。
在这种情况下,您应该:
为每个客户端提供自己的ADO连接和查询对象。你可以:
一个。在TIdTCPServer
事件中创建它们并将它们存储在OnConnect
中以便在TIdContext
事件中使用,然后在OnExecute
eventt中释放它们。或者根据需要在OnDisconnect
事件中创建并释放它们。
B中。从OnExecute
派生一个新类并覆盖其虚拟TIdThreadWithTask
和BeforeExecute()
方法以创建和释放ADO对象,然后将AfterExecute()
个组件之一分配给{{ 1}}属性并将您的线程类分配给TIdSchedulerOfThread...
属性。然后,在服务器事件中,您可以使用TIdTCPServer.Scheduler
来访问调用线程的ADO对象。
创建一个单独的ADO对象池。当客户端需要访问数据库时,让它将适当的ADO对象编组到调用线程的上下文中,然后在完成后将对象放回池中。
无论哪种方式,由于ADO是基于COM的,不要忘记为TIdSchedulerOfThread.ThreadClass
和TMyThreadClass(TIdYarnOfThread(TIdContext.Yarn).Thread)
调用需要访问ADO对象的每个客户端线程,{{1} }和CoInitialize/Ex()
个事件,或CoUnintialize()
和OnConnect
方法。