delphi – 如何获取dbExpress连接错误的Winsock错误代码?

delphi – 如何获取dbExpress连接错误的Winsock错误代码?,第1张

概述如果出现连接问题,dbExpress驱动程序将抛出TDBXError但不包含套接字错误代码.消息很简单: Unable to complete network request to host “exampledb.local”. Failed to establish a connection 有没有办法在发生此类异常时检索底层套接字错误? 堆栈跟踪是: main thread ($5934): 如果出现连接问题,dbExpress驱动程序将抛出TDBXError但不包含套接字错误代码.消息很简单:

Unable to complete network request to host “exampledb.local”.
Failed to establish a connection

有没有办法在发生此类异常时检索底层套接字错误?

堆栈跟踪是:

main thread (34):0061aa59 +051 example.exe DBXCommon    447  +0 TDBXContext.Error00817f14 +10c example.exe DBXDynalink  796 +21 TDBXMethodtable.raiseerror00818553 +013 example.exe DBXDynalink  949  +1 TDBXDynalinkConnection.CheckResult00818744 +050 example.exe DBXDynalink 1048  +4 TDBXDynalinkConnection.DerivedOpen0061750f +007 example.exe DBXCommon    447  +0 TDBXConnection.Open00612fed +0f5 example.exe DBXCommon    447  +0 TDBXConnectionFactory.GetConnection00612ef1 +005 example.exe DBXCommon    447  +0 TDBXConnectionFactory.GetConnection0062c08f +26f example.exe sqlExpr              TsqlConnection.DoConnect005d9019 +039 example.exe DB                   TCustomConnection.SetConnected005d8fd4 +004 example.exe DB                   TCustomConnection.Open0062b98f +01b example.exe sqlExpr              TsqlConnection.CheckConnection0062ebdf +01f example.exe sqlExpr              TCustomsqlDataSet.CheckConnection0062efe4 +04c example.exe sqlExpr              TCustomsqlDataSet.OpenCursor005e91d5 +055 example.exe DB                   TDataSet.SetActive005e901c +004 example.exe DB                   TDataSet.Open
解决方法 (在这个答案中使用Delphi XE2和’gds32.dll’10.0.1.335(ansi))

dbExpress是一个高级框架,它将提供程序特定的 *** 作委托给其驱动程序.所有这些提供程序特定的驱动程序都公开相同的基本公共功能,因此无法检索超出此常用功能的特定信息.

关于错误报告,驱动程序导出两个函数.无论是MysqL还是mssql或任何其他驱动程序,这些函数都是DBXBase_GetErrorMessageLength和DBXBase_GetErrorMessage.驱动程序从客户端库中获取大部分错误,并通过这些函数将该信息报告给框架.除了已经报告的内容之外,无法获得有关连接到数据库服务器或任何其他 *** 作的错误的更具体细节.

因此,客户端库是否包含winsock错误信息.对于问题中包含的错误的interbase驱动程序,此信息已包含在内(当存在时).

下面是一个示例案例,尝试连接到现有服务器,以及侦听但不是数据库服务器的端口.

Connection := TsqlConnection.Create(nil);  Connection.Drivername := 'Interbase';  Connection.Params.Values['Database'] := 'existingserver/80:database';  try    Connection.Open;  except    on E: TDBxError do begin      writeln(E.Message + slineBreak);

这是输出:

Unable to complete network request to host “existingserver:80”.
Failed to establish a connection.

正如您所注意到的那样,问题中的错误信息完全相同.请注意,文本中没有winsock错误.这是因为没有winsock错误,只要涉​​及网络协议,连接实际上是成功的.

这是对现有服务器的尝试,但是对非侦听端口的尝试.

Connection := TsqlConnection.Create(nil);  Connection.Drivername := 'Interbase';  Connection.Params.Values['Database'] := 'existingserver/81:database';  try    Connection.Open;  except    on E: TDBxError do begin      writeln(E.Message + slineBreak);

这是返回的错误:

Unable to complete network request to host “existingserver:81”.
Failed to establish a connection.
unkNown Win32 error 10060

这次连接失败,因为没有特定端口的侦听器.我不知道为什么客户端库无法解析10060,但这是你的winsock错误.

localhost,非监听端口的情况:

Unable to complete network request to host “localhost:3051”.
Failed to establish a connection.
No connection Could be made because the target machine actively refused it.

这里我们有一个10061.

当尝试连接到不可解析的主机时,gds32.dll不会报告任何API错误.我不知道库如何解析主机或为什么它不包含错误代码,但错误消息是详细的:

Unable to complete network request to host “nonexistingserver”.
Failed to locate host machine.
The specifIEd name was not found in the hosts file or Domain name Services.

如果我们直接使用客户端库,我们只能得到API错误.检查以下程序,其中尝试连接到现有服务器和关闭的端口.

program Project1;{$APPTYPE CONSolE}{$R *.res}uses  system.sysutils,data.dbxcommon,data.sqlexpr,data.dbxinterbase;function isc_attach_database(status_vector: PLongint; db_name_length: Smallint;    db_name: PAnsiChar; db_handle: PPointer; parm_buffer_length: Smallint;    parm_buffer: PAnsiChar): Longint; stdcall; external 'gds32.dll';function isc_interprete(buffer: PAnsiChar; var status_vector: Pointer): Longint;    stdcall; external 'gds32.dll';var  Connection: TsqlConnection;  Statusvector: array[0..19] of Longint;  Handle: PPointer;  Error: array[0..255] of AnsiChar;  IntrStatus: Pointer;  s: string;begin  try    Connection := TsqlConnection.Create(nil);    Connection.Drivername := 'Interbase';    Connection.Params.Values['Database'] := 'server/3051:database'; // closed port    try      Connection.Open;    except      on E: TDBxError do begin        writeln(E.Message + slineBreak);        if E.ErrorCode = TDBXErrorCodes.ConnectionFailed then begin          Handle := nil;          if isc_attach_database(@Statusvector,PAnsiChar(AnsiString(Connection.Params.Values['Database'])),@Handle,nil) <> 0 then begin            IntrStatus := @Statusvector;            s := '';            while isc_interprete(Error,IntrStatus) <> 0 do begin              s := s + AnsiString(Error) + slineBreak;              if PLongint(IntrStatus)^ = 17 then  // isc_arg_win32                s := s + ' --below is an API error--' + slineBreak +                     Format('%d: %s',[PLongint(Longint(IntrStatus) + 4)^,SysErrorMessage(PLongint(Longint(IntrStatus) + 4)^)]) +                     slineBreak;            end;            Writeln(s);          end;        end else          raise;      end;    end;  except    on E: Exception do      Writeln(E.Classname,': ',E.Message);  end;  readln;end.

哪个输出:

Unable to complete network request to host “sever:3051”.
Failed to establish a connection.
unkNown Win32 error 10060

Unable to complete network request to host “server:3051”.
Failed to establish a connection.
–below is an API error–
10060: A connection attempt Failed because the connected party dID not properly
respond after a period of time,or established connection Failed because connect
ed host has Failed to respond
unkNown Win32 error 10060

第一段是dbx报告的内容.第二段是我们从’gds32.dll’获得的,包括注入API错误代码和文本,否则它们是相同的.

以上是一个粗略的演示,正确的打字使用’interbase.h’.有关选择可能的API错误的详细信息,请参阅“Parsing the Status Vector”或一般“Handling Error Conditions”.

在任何情况下,可以看出,能够完全获取特定信息取决于dbx用于连接数据库服务器的客户端库.

对于一般情况,要独立于正在使用的数据库服务器获取winsock错误信息,您可以做的是尝试在尝试打开数据库连接之前将套接字连接到服务器,并且只有在成功时才关闭测试连接然后继续附加到数据库.您可以使用任何库或裸API来执行此 *** 作.

这是一个简单的例子:

function TestConnect(server: string; port: Integer): Boolean;  procedure Winsockerror(step: string);  begin    raise Exception.Create(Format('"%s" fail. %d: %s:',[step,WSAGetLastError,SysErrorMessage(WSAGetLastError)]));    end;var  Error: Integer;  Data: TWSAData;  Socket: TSocket;  SockAddr: TSockAddrIn;  Host: PHostEnt;begin  Result := False;  Error := WSAStartup(MakeWord(1,1),Data);  if Error = 0 then begin    try      Socket := winsock.socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);      if Socket <> INVALID_SOCKET then begin        try          Host := gethostbyname(PAnsiChar(AnsiString(server)));          if Host <> nil then begin            SockAddr.sin_family := AF_INET;            SockAddr.sin_addr.S_addr := Longint(PLongint(Host^.h_addr_List^)^);            SockAddr.sin_port := htons(port);            if connect(Socket,SockAddr,SizeOf(SockAddr)) <> 0 then              Winsockerror('connect')            else              Result := True;          end else            Winsockerror('gethostbyname');        finally          closesocket(Socket);        end;        end else        Winsockerror('socket');    finally        WSACleanup;    end;    end else    raise Exception.Create('winsock initialization fail');end;

你可以使用这样的东西:

if TestConnect('server',3050) then  //
总结

以上是内存溢出为你收集整理的delphi – 如何获取dbExpress连接错误的Winsock错误代码?全部内容,希望文章能够帮你解决delphi – 如何获取dbExpress连接错误的Winsock错误代码?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1271501.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存