连接远程数据库服务器,如果远程服务器未开机,程序就会停顿几分钟,就象死了 一样(BDE一般约3分钟后恢复正常)。
在连接远程数据库服务器前,先使用TClientSocket连接端口(测试端口,时间3秒足够),如果TClientSocket连接不上,就不再使用数据库连接组件(ADO-TADOConnection或BDE-TDatabase)连接了。
使用TClientSocket连接端口时,要使用线程来控制时间,并使用阻塞型连接,线程内时间一到就取消Socket, (如果端口有效,那是一连就通,如数据库服务未开,而服务器存在,也很快被拒绝,而服务器不存在时,可能时间较长,这时TClientSocket将发生作用)。
//--------------------------------------------------------------------------- // 线程写法: //--------------------------------------------------------------------------- class TThreadConnPort : public TThread { private: int MaxTimeOut; TClientSocket *SocketPoint; void __fastcall Execute(void); public: __fastcall TThreadConnPort(TClientSocket *ClientSocket, int TimeOut); }; //--------------------------------------------------------------------------- __fastcall TThreadConnPort::TThreadConnPort(TClientSocket *ClientSocket, int TimeOut) : TThread(true) { SocketPoint = ClientSocket; MaxTimeOut = TimeOut; // 控制时间 FreeOnTerminate = true; Resume(); } //--------------------------------------------------------------------------- void __fastcall TThreadConnPort::Execute(void) { int TimeCount = 0; Sleep(300); while (!Terminated) { TimeCount++; try { if (SocketPoint->Tag) break; else if (TimeCount > MaxTimeOut * 10) { SocketPoint->Socket->Close(); SocketPoint->Close(); break; } } catch (...) { break; } Sleep(100); } } //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- // ConnectionServerPort() 是测试主机与端口的函数 // AnsiString ServerIp 主机名或IP地址, // int ServerPort 端口号,1-65535 // int TimeOut 控制时间,秒 // 这个函数返回值表示远程主机的数据库服务端口是否有效 //--------------------------------------------------------------------------- bool __fastcall TMainForm::ConnectionServerPort(AnsiString ServerIp, int ServerPort, int TimeOut) { bool PortConnected; TClientSocket *ClientSocket = new TClientSocket(this); ClientSocket->Tag = 0; ClientSocket->OnConnect = ClientSocketConnect; // 连接成功时,将Tag置1表示成功 ClientSocket->OnError = ClientSocketError; // 连接异常时处理函数 ClientSocket->Host = ServerIp; ClientSocket->Port = ServerPort; ClientSocket->ClientType = ctBlocking; TThreadConnPort * CheckSocket = new TThreadConnPort(ClientSocket, TimeOut); try { ClientSocket->Open(); CheckSocket->Terminate(); } catch (...) { ClientSocket->Tag=0; } PortConnected = ClientSocket->Tag == 1; // 查询是否成功 delete ClientSocket; return PortConnected; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ClientSocketConnect(TObject *Sender, TCustomWinSocket *Socket) { TClientSocket *SocketId = (TClientSocket *)Sender; SocketId->Tag = 1; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ClientSocketError(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode) { TClientSocket *SocketId = (TClientSocket *)Sender; if (ErrorEvent == eeLookup) SocketId->Tag = 2; else SocketId->Tag = 3; ErrorCode = 0; } //---------------------------------------------------------------------------
// 在连接数据库前使用 ConnectionServerPort() 函数测试端口 // 由于连接时,可能使用客户端工具生成的连接名,那么,要进行地址解释。

|