服务端连接数据库正常,但客户端有时正常,有时就连接不上,但服务端和客户端的UDP通讯正常。客户端连接不正常时出现"dbnetlib connectionread[(recv().)]一般性网络错误" , 比较奇怪的是客户端并不是每次都连接不上, 只是偶尔, 而且出现问题的客户端不固定. 客户端数量 50 台环境: Delphi7 + SQL Server 2000(SP4), 客户端xp, 服务器端 xp, 数据库服务器 WINDOWS2003我在客户端有一个测试连接数据库的函数, 服务端发送命令, 客户端便尝试连接, 如果出错则将错误信息通过 UDP 返回给服务端.对于该问题, 我在大富翁上找到如下解决方法:
//_____________________________________________________________________
大富翁:ID=1097834
  用ADO连接SQL SERVER出错,第一次连接正常,第二次出错,再连又正常,如此反复
  猛禽 (2002-05-14 16:11:00)  
  终于解决了,原来是ADOConnection需要唯一标识,否则SQL Server会进行缓存。  shuizi2000 (2002-11-18 10:27:00)
  To:猛禽
    你是怎么做的呀?怎么做ADOConnection的唯一标识?谢谢  猛禽 (2002-11-19 15:32:00)
  在ConnectionString中指定Application Name,保有证每个Connection的Application Name
  不相同即可
//_____________________________________________________________________我也试过了, 将每个客户端的Application Name 设置为本机IP地址, 这样不会有重复的了吧, 当还是出现. 曾见有高手说:
try
    ADOConnection1.Connected := False;
    ADOConnection1.Connected := True;
except
    有问题
end;
我也试验过, 假如拔掉网线后再插上, 使用以上代码不会"有问题" ,但 ADOQuery 查询时会出错.下面我给出我测试数据库连接的函数:
function TfrmCoverBase.TestDatabaseConnection( blnSendToServer: boolean;
  blnKeepConnection: boolean; Popwin: TfrmPopwin ): boolean;
var
  i: integer;
  frmPopwin: TfrmPopwin;
begin
  result := false;  if Popwin = nil then
    frmPopwin := ShowPopWin('正在连接数据库,请稍候...',false)
  else
  begin
    frmPopwin := Popwin;
    frmPopwin.UpdateInfo('正在连接数据库,请稍候...');
  end;
  try
    //测试连接是否断开
    dmData.AConnServer.Connected := false;
    try
      dmData.AConnServer.Connected := true;//_____________通过错误信息发现,主要是这个地方出错
      try
        with dmData.qryTempS do
        begin
          Close;
          SQL.Clear;
          SQL.Add('SELECT GETDATE()');
          Open;
          Close;
          result := true;
          if blnSendToServer then
          begin
            Send(CMD_REPORT + CMD_REPORT_INFO + '数据库连接测试成功');
            frmPopwin.UpdateInfo('数据库连接测试成功');
          end;
        end;
      except
        dmData.AConnServer.Connected := false;
        try
          dmData.AConnServer.Connected := true;
        except
          on E: Exception do
          begin
            result := false;
            if blnSendToServer then
            begin
              Send(CMD_REPORT + CMD_REPORT_ERROR + '数据库连接测试失败:' + E.Message); //和下面Except的冒号不一样,以便考官端判断错误位置。
              frmPopwin.UpdateInfo('数据库连接测试失败:' + E.Message);
            end;
          end;
        end;
      end;
    except
      on E: Exception do
      begin
        result := false;
        if blnSendToServer then
        begin
          Send(CMD_REPORT + CMD_REPORT_ERROR + '数据库连接测试失败:' + E.Message);
          frmPopwin.UpdateInfo('数据库连接测试失败:' + E.Message);
        end;
      end;
    end;
  finally
    if not blnKeepConnection then
      dmData.AConnServer.Connected := false;
    frmPopwin.AutoClose := true;
  end;
end;
这个问题困扰了我快一年了, 不知道大家是否遇到过类似的问题

解决方案 »

  1.   

    引用一段:
    halfdream(哈欠) (****) 信誉:144每次有人找我问起楼主那个经典问题,我都是同样的回答..
    可几乎每次问问题的人总以为我在开玩笑.当数据库连接断开时,这时候需要做什么呢?是试图重连?不断检查连接状态? 
    NO! 不要这样做!
    数据库为什么断开?多半网络问题或者数据库当机或重启.事实上,这时候试图程序自动重连,
    毫无意义!这样做反而会为负担很重的网络更没有恢复的机会.这时候该做什么? 是的,释放连接对象,很多封装底层连接的组件,都会暂存连接状态,
    当底层实际连接失败,封装对象的状态却是连接正常,这时候,连接不可能得到恢复.
    怎么让封装对象与底层连接状态一致? 很简单,让连接对象CLOSE!怎么知道连接失败? 在对数据库操作时! 对于VCL,组件会扔出数据库类型的异常,要做的,就是抓住它.对于使用数据感知控件,在Application.OnException事件中也可以得到它.
    在处理这样异常时,就按刚才说的那样,"让连接对象CLOSE"!对于状态为CLOSE的连接对象,不需要再操心什么.在使用VCL封装Ado时,当连接对象AdoConnection状态为关闭时,任何一个数据库的操作,它都会自动去连接.这是缺省的属性设计.
    ----------------针对我的问题, 我请教一下:-------------------
    这时候该做什么? 是的,释放连接对象,很多封装底层连接的组件,都会暂存连接状态,
    当底层实际连接失败,封装对象的状态却是连接正常,这时候,连接不可能得到恢复.
    怎么让封装对象与底层连接状态一致? 很简单,让连接对象CLOSE!
    -------- 是说 将 dmData.AConnServer.Connected := false; 改为
    dmData.AConnServer.Close; 吗?
    对于状态为CLOSE的连接对象,不需要再操心什么.在使用VCL封装Ado时,当连接对象AdoConnection状态为关闭时,任何一个数据库的操作,它都会自动去连接.这是缺省的属性设计.
    -------- 假如我每次用完后 Close, 下次查询时是否不需要 Open 或 Connected := true;
      

  2.   

    还请高手解释一下:
    AConnServer.Connected := false; 与 AConnServer.Close 的区别
    AConnServer.Connected := true; 与 AConnServer.Open 的区别