www.pudn.com > woool12.rar > IdSrvClient.pas


unit IdSrvClient; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ExtCtrls, IniFiles,  WinSock, Grobal2, MudUtil, M2Share,MyList, 
  UnitManage, ScktComp; 
 
type 
  TFrmIDSoc = class(TForm) 
    IDSocket: TClientSocket; 
    Timer1: TTimer; 
    procedure Timer1Timer(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure IDSocketError(Sender: TObject; Socket: TCustomWinSocket; 
      ErrorEvent: TErrorEvent; var ErrorCode: Integer); 
    procedure IDSocketRead(Sender: TObject; Socket: TCustomWinSocket); 
    procedure IDSocketConnect(Sender: TObject; Socket: TCustomWinSocket); 
    procedure IDSocketDisconnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
  private 
 
    TList_2DC: TMyList; 
    IDSrvAddr: string;                  //0x2E0 
    IDSrvPort: Integer;                 //0x2E4 
    //    sIDSckStr :String; //0x2E8 
    //    boConnected:Boolean; 
    dwClearEmptySessionTick: LongWord; 
    procedure GetPasswdSuccess(sData: string); 
    procedure GetCancelAdmission(sData: string); 
    procedure GetCancelAdmissionA(sData: string); 
    procedure SetTotalHumanCount(sData: string); 
    procedure GetServerLoad(sData: string); 
    procedure DelSession(nSessionID: Integer); 
    procedure NewSession(sAccount, sIPaddr: string; nSessionID, nPayMent, 
      nPayMode: Integer); 
    procedure ClearSession(); 
    procedure ClearEmptySession(); 
    procedure SendSocket(sSENDMSG: string); 
    { Private declarations } 
  public 
    m_SessionList: TGList;              //0x2D8 
    procedure Initialize(); 
    procedure Run(); 
    procedure SendOnlineHumCountMsg(nCount: Integer); 
    procedure SendHumanLogOutMsg(sUserID: string; nID: Integer); 
    function GetAdmission(sAccount, sIPaddr: string; nSessionID: Integer; var 
      nPayMode: Integer; var nPayMent: Integer): pTSessInfo; 
    function GetSessionCount(): Integer; 
    procedure GetSessionList(List: TMyList); 
    procedure SendLogonCostMsg(sAccount: string; nTime: Integer); 
    procedure Close(); 
    { Public declarations } 
  end; 
procedure IDSocketThread(ThreadInfo: pTThreadInfo); stdcall; 
var 
  FrmIDSoc          : TFrmIDSoc; 
 
implementation 
 
uses HUtil32; 
 
{$R *.dfm} 
 
{ TFrmIDSoc } 
 
 
 
procedure TFrmIDSoc.FormCreate(Sender: TObject); 
var 
  Conf              : TIniFile; 
begin 
  IDSocket.Host := ''; 
  if FileExists(sConfigFileName) then 
  begin 
    Conf := TIniFile.Create(sConfigFileName); 
    if Conf <> nil then 
    begin 
      IDSrvAddr := Conf.ReadString('Server', 'IDSAddr', '127.0.0.1'); 
      IDSrvPort := Conf.ReadInteger('Server', 'IDSPort', 5600); 
    end; 
    Conf.Free; 
  end 
  else 
    ShowMessage('配置文件' + sConfigFileName + '未找到!!!'); 
 
  m_SessionList := TGList.Create; 
  TList_2DC := TMyList.Create; 
  g_Config.boIDSocketConnected := False; 
  //    sub_48D290(); 
end; 
 
procedure TFrmIDSoc.FormDestroy(Sender: TObject); 
begin 
  ClearSession(); 
  m_SessionList.Free; 
  TList_2DC.Free; 
end; 
 
procedure TFrmIDSoc.Timer1Timer(Sender: TObject); 
begin 
  if not IDSocket.Active then 
  begin 
    IDSocket.Active := True; 
  end; 
end; 
 
procedure TFrmIDSoc.IDSocketError(Sender: TObject; 
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
  var ErrorCode: Integer); 
begin 
  ErrorCode := 0; 
  Socket.Close; 
end; 
 
procedure TFrmIDSoc.IDSocketRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  EnterCriticalSection(g_Config.UserIDSection); 
  try 
    g_Config.sIDSocketRecvText := g_Config.sIDSocketRecvText + 
      Socket.ReceiveText; 
  finally 
    LeaveCriticalSection(g_Config.UserIDSection); 
  end; 
end; 
 
procedure TFrmIDSoc.Initialize;         //0048D3F8 
begin 
  IDSocket.Active := False; 
  IDSocket.Address := IDSrvAddr; 
  IDSocket.Port := IDSrvPort; 
  IDSocket.Active := True; 
  Timer1.Enabled := True; 
end; 
{$IF IDSOCKETMODE = TIMERENGINE} 
 
procedure TFrmIDSoc.SendSocket(sSENDMSG: string); 
begin 
  if IDSocket.Socket.Connected then 
  begin 
    IDSocket.Socket.SendText(sSENDMSG); 
  end; 
end; 
{$ELSE} 
 
procedure TFrmIDSoc.SendSocket(sSENDMSG: string); 
var 
  boSendData        : Boolean; 
  Config            : pTConfig; 
  ThreadInfo        : pTThreadInfo; 
  timeout           : TTimeVal; 
  writefds          : TFDSet; 
  nRet              : Integer; 
  s                 : TSocket; 
begin 
  Config := @g_Config; 
  ThreadInfo := @g_Config.DBSOcketThread; 
  s := Config.IDSocket; 
  boSendData := False; 
  while True do 
  begin 
    if not boSendData then 
      Sleep(1) 
    else 
      Sleep(0); 
    boSendData := False; 
    ThreadInfo.dwRunTick := GetTickCount(); 
    ThreadInfo.boActived := True; 
    ThreadInfo.nRunFlag := 128; 
 
    ThreadInfo.nRunFlag := 129; 
    timeout.tv_sec := 0; 
    timeout.tv_usec := 20; 
 
    writefds.fd_count := 1; 
    writefds.fd_array[0] := s; 
 
    nRet := select(0, nil, @writefds, nil, @timeout); 
    if nRet = SOCKET_ERROR then 
    begin 
      nRet := WSAGetLastError(); 
      Config.nIDSocketWSAErrCode := nRet - WSABASEERR; 
      Inc(Config.nIDSocketErrorCount); 
      if nRet = WSAEWOULDBLOCK then 
      begin 
        Continue; 
      end; 
      if Config.IDSocket = INVALID_SOCKET then 
        break; 
      Config.IDSocket := INVALID_SOCKET; 
      Sleep(100); 
      Config.boIDSocketConnected := False; 
      break; 
    end; 
    if nRet <= 0 then 
    begin 
      Continue; 
    end; 
    boSendData := True; 
    nRet := send(s, sSENDMSG[1], Length(sSENDMSG), 0); 
    if nRet = SOCKET_ERROR then 
    begin 
      Inc(Config.nIDSocketErrorCount); 
      Config.nIDSocketWSAErrCode := WSAGetLastError - WSABASEERR; 
      Continue; 
    end; 
    Inc(Config.nDBSocketSendLen, nRet); 
    break; 
  end; 
end; 
{$IFEND} 
 
procedure TFrmIDSoc.SendHumanLogOutMsg(sUserID: string; nID: Integer); //0048D448 
var 
  i                 : Integer; 
  SessInfo          : pTSessInfo; 
resourcestring 
  sFormatMsg        = '(%d/%s/%d)'; 
begin 
  m_SessionList.Lock; 
  try 
    for i := 0 to m_SessionList.Count - 1 do 
    begin 
      SessInfo := m_SessionList.Items[i]; 
      if (SessInfo.nSessionID = nID) and (SessInfo.sAccount = sUserID) then 
      begin 
        //SessInfo.dwCloseTick:=GetTickCount(); 
        //SessInfo.boClosed:=True; 
        break; 
      end; 
    end; 
  finally 
    m_SessionList.UnLock; 
  end; 
  SendSocket(format(sFormatMsg, [SS_SOFTOUTSESSION, sUserID, nID])); 
end; 
 
procedure TFrmIDSoc.SendLogonCostMsg(sAccount: string; nTime: Integer); 
//0048D53C 
resourcestring 
  sFormatMsg        = '(%d/%s/%d)'; 
begin 
  SendSocket(format(sFormatMsg, [SS_LOGINCOST, sAccount, nTime])); 
end; 
 
procedure TFrmIDSoc.SendOnlineHumCountMsg(nCount: Integer); 
resourcestring 
  sFormatMsg        = '(%d/%s/%d/%d)'; 
begin 
  SendSocket(format(sFormatMsg, [SS_SERVERINFO, g_Config.sServerName, 
    nServerIndex, nCount])); 
end; 
 
procedure TFrmIDSoc.Run;                //0048D724 
var 
  sSocketText       : string; 
  sData             : string; 
  sBody             : string; 
  sCode             : string; 
  nLen              : Integer; 
  Config            : pTConfig; 
resourcestring 
  sExceptionMsg     = '[Exception] TFrmIdSoc::DecodeSocStr'; 
begin 
  Config := @g_Config; 
  EnterCriticalSection(Config.UserIDSection); 
  try 
    if Pos(')', Config.sIDSocketRecvText) <= 0 then 
      exit; 
    sSocketText := Config.sIDSocketRecvText; 
    Config.sIDSocketRecvText := ''; 
  finally 
    LeaveCriticalSection(Config.UserIDSection); 
  end; 
  try 
    while (True) do 
    begin 
      sSocketText := ArrestStringEx(sSocketText, '(', ')', sData); 
      if sData = '' then 
        break; 
      sBody := GetValidStr3(sData, sCode, ['/']); 
      case Str_ToInt(sCode, 0) of 
        SS_OPENSESSION {100}: GetPasswdSuccess(sBody); 
        SS_CLOSESESSION {101}: GetCancelAdmission(sBody); 
        SS_KEEPALIVE {104}: SetTotalHumanCount(sBody); 
        UNKNOWMSG: ; 
        SS_KICKUSER {111}: GetCancelAdmissionA(sBody); 
        SS_SERVERLOAD {113}: GetServerLoad(sBody); 
      end; 
      if Pos(')', sSocketText) <= 0 then 
        break; 
    end; 
    EnterCriticalSection(Config.UserIDSection); 
    try 
      Config.sIDSocketRecvText := sSocketText + Config.sIDSocketRecvText; 
    finally 
      LeaveCriticalSection(Config.UserIDSection); 
    end; 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
  if GetTickCount - dwClearEmptySessionTick > 10000 then 
  begin 
    dwClearEmptySessionTick := GetTickCount(); 
    //ClearEmptySession(); 
  end; 
{$IF (DEBUG = 0) and (SoftVersion <> VERDEMO)} 
  if IsDebuggerPresent then 
    Application.Terminate; 
{$IFEND} 
end; 
 
procedure TFrmIDSoc.GetPasswdSuccess(sData: string); //0048D9B4 
var 
  sAccount          : string; 
  sSessionID        : string; 
  sPayCost          : string; 
  sIPaddr           : string; 
  sPayMode          : string; 
resourcestring 
  sExceptionMsg     = '[Exception] TFrmIdSoc::GetPasswdSuccess'; 
begin 
  try 
    sData := GetValidStr3(sData, sAccount, ['/']); 
    sData := GetValidStr3(sData, sSessionID, ['/']); 
    sData := GetValidStr3(sData, sPayCost, ['/']); //boPayCost 
    sData := GetValidStr3(sData, sPayMode, ['/']); //nPayMode 
    sData := GetValidStr3(sData, sIPaddr, ['/']); //sIPaddr 
    NewSession(sAccount, sIPaddr, Str_ToInt(sSessionID, 0), Str_ToInt(sPayCost, 
      0), Str_ToInt(sPayMode, 0)); 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
procedure TFrmIDSoc.GetCancelAdmission(sData: string); //0048DB60 
var 
  SC, sSessionID    : string; 
resourcestring 
  sExceptionMsg     = '[Exception] TFrmIdSoc::GetCancelAdmission'; 
begin 
  try 
    sSessionID := GetValidStr3(sData, SC, ['/']); 
    DelSession(Str_ToInt(sSessionID, 0)); 
  except 
    on E: Exception do 
    begin 
      MainOutMessage(sExceptionMsg); 
      MainOutMessage(E.Message); 
    end; 
  end; 
end; 
 
procedure TFrmIDSoc.NewSession(sAccount, sIPaddr: string; nSessionID, nPayMent, 
  nPayMode: Integer);                   //0048DC44 
var 
  SessInfo          : pTSessInfo; 
begin 
  New(SessInfo); 
  SessInfo.sAccount := sAccount; 
  SessInfo.sIPaddr := sIPaddr; 
  SessInfo.nSessionID := nSessionID; 
  SessInfo.nPayMent := nPayMent; 
  SessInfo.nPayMode := nPayMode; 
  SessInfo.nSessionStatus := 0; 
  SessInfo.dwStartTick := GetTickCount(); 
  SessInfo.dwActiveTick := GetTickCount(); 
  SessInfo.nRefCount := 1; 
  m_SessionList.Lock; 
  try 
    m_SessionList.Add(SessInfo); 
  finally 
    m_SessionList.UnLock; 
  end; 
end; 
 
procedure TFrmIDSoc.DelSession(nSessionID: Integer); //0048DD5C 
var 
  i                 : Integer; 
  sAccount          : string; 
  SessInfo          : pTSessInfo; 
resourcestring 
  sExceptionMsg     = '[Exception] FrmIdSoc::DelSession %d'; 
begin 
  try 
 
    sAccount := ''; 
    m_SessionList.Lock; 
    try 
 
      for i := 0 to m_SessionList.Count - 1 do 
      begin 
        SessInfo := m_SessionList.Items[i]; 
 
        if SessInfo.nSessionID = nSessionID then 
        begin 
          sAccount := SessInfo.sAccount; 
          m_SessionList.Delete(i); 
          DisPose(SessInfo); 
          break; 
        end; 
      end; 
 
    finally 
      m_SessionList.UnLock; 
    end; 
 
    if sAccount <> '' then 
    begin 
 
      RunSocket.KickUser(sAccount, nSessionID); 
 
    end; 
 
  except 
    on E: Exception do 
    begin 
      MainOutMessage(format(sExceptionMsg, [0])); 
      MainOutMessage(E.Message); 
    end; 
  end; 
 
end; 
 
procedure TFrmIDSoc.ClearEmptySession; 
var 
  i                 : Integer; 
  SessInfo          : pTSessInfo; 
begin 
  m_SessionList.Lock; 
  try 
    for i := m_SessionList.Count - 1 downto 0 do 
    begin 
      SessInfo := m_SessionList.Items[i]; 
      if SessInfo.nRefCount <= 0 then 
      begin 
        DisPose(SessInfo); 
        m_SessionList.Delete(i); 
        Continue; 
      end; 
      { 
      if GetTickCount - SessInfo.dwActiveTick > 10 * 60 * 1000 then begin 
        Dispose(SessInfo); 
        m_SessionList.Delete(I); 
        Continue; 
      end; 
      } 
    end; 
  finally 
    m_SessionList.UnLock; 
  end; 
end; 
 
procedure TFrmIDSoc.ClearSession; 
var 
  i                 : Integer; 
begin 
  m_SessionList.Lock; 
  try 
    for i := 0 to m_SessionList.Count - 1 do 
    begin 
      DisPose(pTSessInfo(m_SessionList.Items[i])); 
    end; 
    m_SessionList.Clear; 
  finally 
    m_SessionList.UnLock; 
  end; 
 
end; 
 
function TFrmIDSoc.GetAdmission(sAccount, sIPaddr: string; nSessionID: Integer; 
  var nPayMode: Integer; var nPayMent: Integer): pTSessInfo; //0048DE80 
var 
  i                 : Integer; 
  nCount            : Integer; 
  SessInfo          : pTSessInfo; 
  boFound           : Boolean; 
resourcestring 
  sGetFailMsg       = '[非法登录] 全局会话验证失败(%s/%s/%d)'; 
begin 
 
  //  Result:=3; 
  //  exit; 
  boFound := False; 
  Result := nil; 
  nPayMent := 0; 
  nPayMode := 0; 
  m_SessionList.Lock; 
  try 
 
    for i := 0 to m_SessionList.Count - 1 do 
    begin 
      SessInfo := m_SessionList.Items[i]; 
 
      if (SessInfo.nSessionID = nSessionID) and 
        (SessInfo.sAccount = sAccount) {and (SessInfo.sIPaddr = sIPaddr)} then 
      begin 
        //if SessInfo.nSessionStatus <> 0 then break; 
        //SessInfo.nSessionStatus:=1; 
 
        case SessInfo.nPayMent of 
          2: nPayMent := 3; 
          1: nPayMent := 2; 
          0: nPayMent := 1; 
        end; 
        Result := SessInfo; 
        nPayMode := SessInfo.nPayMode; 
        boFound := True; 
 
        break; 
      end; 
    end; 
 
  finally 
    m_SessionList.UnLock; 
  end; 
 
  if g_Config.boViewAdmissionFailure and not boFound then 
  begin 
    MainOutMessage(format(sGetFailMsg, [sAccount, sIPaddr, nSessionID])); 
  end; 
 
end; 
 
procedure TFrmIDSoc.SetTotalHumanCount(sData: string); //0048E014 
begin 
  g_nTotalHumCount := Str_ToInt(sData, 0) 
end; 
 
procedure TFrmIDSoc.GetCancelAdmissionA(sData: string); //0048E06C 
var 
  nSessionID        : Integer; 
  sSessionID        : string; 
  sAccount          : string; 
resourcestring 
  sExceptionMsg     = '[Exception] FrmIdSoc::GetCancelAdmissionA'; 
begin 
  try 
    sSessionID := GetValidStr3(sData, sAccount, ['/']); 
    nSessionID := Str_ToInt(sSessionID, 0); 
    if not g_Config.boTestServer then 
    begin 
      UserEngine.HumanExpire(sAccount); 
      DelSession(nSessionID); 
    end; 
  except 
    MainOutMessage(sExceptionMsg); 
  end; 
end; 
 
 
procedure TFrmIDSoc.GetServerLoad(sData: string); //0048E174 
var 
  SC, s10, s14, s18, s1C: string; 
begin 
  sData := GetValidStr3(sData, SC, ['/']); 
  sData := GetValidStr3(sData, s10, ['/']); 
  sData := GetValidStr3(sData, s14, ['/']); 
  sData := GetValidStr3(sData, s18, ['/']); 
  sData := GetValidStr3(sData, s1C, ['/']); 
  nCurrentMonthly := Str_ToInt(SC, 0); 
  nLastMonthlyTotalUsage := Str_ToInt(s10, 0); 
  nTotalTimeUsage := Str_ToInt(s14, 0); 
  nGrossTotalCnt := Str_ToInt(s18, 0); 
  nGrossResetCnt := Str_ToInt(s1C, 0); 
end; 
 
procedure TFrmIDSoc.IDSocketConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  g_Config.boIDSocketConnected := True; 
  MainOutMessage('登录服务器(' + Socket.RemoteAddress + ':' + 
    IntToStr(Socket.RemotePort) + ')连接成功...'); 
end; 
 
procedure TFrmIDSoc.IDSocketDisconnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
  if g_Config.boIDSocketConnected then 
  begin 
    ClearSession(); 
    g_Config.boIDSocketConnected := False; 
    MainOutMessage('登录服务器(' + Socket.RemoteAddress + ':' + 
      IntToStr(Socket.RemotePort) + ')断开连接...'); 
  end; 
end; 
{$IF IDSOCKETMODE = TIMERENGINE} 
 
procedure TFrmIDSoc.Close; 
begin 
  Timer1.Enabled := False; 
  IDSocket.Active := False; 
end; 
{$ELSE} 
 
procedure TFrmIDSoc.Close; 
var 
  ThreadInfo        : pTThreadInfo; 
begin 
  ThreadInfo := @g_Config.IDSocketThread; 
  ThreadInfo.boTerminaled := True; 
  if WaitForSingleObject(ThreadInfo.hThreadHandle, 1000) <> 0 then 
  begin 
    SuspendThread(ThreadInfo.hThreadHandle); 
  end; 
end; 
{$IFEND} 
 
function TFrmIDSoc.GetSessionCount: Integer; 
begin 
  Result := 0; 
  m_SessionList.Lock; 
  try 
    Result := m_SessionList.Count; 
  finally 
    m_SessionList.UnLock; 
  end; 
end; 
 
procedure TFrmIDSoc.GetSessionList(List: TMyList); 
var 
  i                 : Integer; 
begin 
  m_SessionList.Lock; 
  try 
    for i := 0 to m_SessionList.Count - 1 do 
    begin 
      List.Add(m_SessionList.Items[i]); 
    end; 
  finally 
    m_SessionList.UnLock; 
  end; 
end; 
 
procedure IDSocketRead(Config: pTConfig); 
var 
  dwReceiveTimeTick : LongWord; 
  nReceiveTime      : Integer; 
  sRecvText         : string; 
  nRecvLen          : Integer; 
  nRet              : Integer; 
begin 
  if Config.IDSocket = INVALID_SOCKET then 
    exit; 
 
  dwReceiveTimeTick := GetTickCount(); 
  nRet := ioctlsocket(Config.IDSocket, FIONREAD, nRecvLen); 
  if (nRet = SOCKET_ERROR) or (nRecvLen = 0) then 
  begin 
    nRet := WSAGetLastError; 
    Config.IDSocket := INVALID_SOCKET; 
    Sleep(100); 
    Config.boIDSocketConnected := False; 
    exit; 
  end; 
  setlength(sRecvText, nRecvLen); 
  nRecvLen := recv(Config.IDSocket, Pointer(sRecvText)^, nRecvLen, 0); 
  setlength(sRecvText, nRecvLen); 
 
  Inc(Config.nIDSocketRecvIncLen, nRecvLen); 
  if (nRecvLen <> SOCKET_ERROR) and (nRecvLen > 0) then 
  begin 
    if nRecvLen > Config.nIDSocketRecvMaxLen then 
      Config.nIDSocketRecvMaxLen := nRecvLen; 
    EnterCriticalSection(Config.UserIDSection); 
    try 
      Config.sIDSocketRecvText := Config.sIDSocketRecvText + sRecvText; 
    finally 
      LeaveCriticalSection(Config.UserIDSection); 
    end; 
    FrmIDSoc.Run; 
  end; 
  Inc(Config.nIDSocketRecvCount); 
  nReceiveTime := GetTickCount - dwReceiveTimeTick; 
  if Config.nIDReceiveMaxTime < nReceiveTime then 
    Config.nIDReceiveMaxTime := nReceiveTime; 
end; 
 
procedure IDSocketProcess(Config: pTConfig; ThreadInfo: pTThreadInfo); 
var 
  s                 : TSocket; 
  Name              : sockaddr_in; 
  HostEnt           : PHostEnt; 
  argp              : LongInt; 
  readfds           : TFDSet; 
  timeout           : TTimeVal; 
  nRet              : Integer; 
  boRecvData        : BOOL; 
  nRunTime          : Integer; 
  dwRunTick         : LongWord; 
resourcestring 
  sIDServerConnected = '登录服务器(%s:%d)连接成功...'; 
begin 
  s := INVALID_SOCKET; 
  if Config.IDSocket <> INVALID_SOCKET then 
    s := Config.IDSocket; 
  dwRunTick := GetTickCount(); 
  ThreadInfo.dwRunTick := dwRunTick; 
  boRecvData := False; 
  while True do 
  begin 
    if ThreadInfo.boTerminaled then 
      break; 
    if not boRecvData then 
      Sleep(1) 
    else 
      Sleep(0); 
    boRecvData := False; 
    nRunTime := GetTickCount - ThreadInfo.dwRunTick; 
    if ThreadInfo.nRunTime < nRunTime then 
      ThreadInfo.nRunTime := nRunTime; 
    if ThreadInfo.nMaxRunTime < nRunTime then 
      ThreadInfo.nMaxRunTime := nRunTime; 
    if GetTickCount - dwRunTick >= 1000 then 
    begin 
      dwRunTick := GetTickCount(); 
      if ThreadInfo.nRunTime > 0 then 
        Dec(ThreadInfo.nRunTime); 
    end; 
 
    ThreadInfo.dwRunTick := GetTickCount(); 
    ThreadInfo.boActived := True; 
    ThreadInfo.nRunFlag := 125; 
    if (Config.IDSocket = INVALID_SOCKET) or (s = INVALID_SOCKET) then 
    begin 
      if Config.IDSocket <> INVALID_SOCKET then 
      begin 
        Config.IDSocket := INVALID_SOCKET; 
        Sleep(100); 
        ThreadInfo.nRunFlag := 126; 
        Config.boIDSocketConnected := False; 
      end; 
      if s <> INVALID_SOCKET then 
      begin 
        closesocket(s); 
        s := INVALID_SOCKET; 
      end; 
      if Config.sIDSAddr = '' then 
        Continue; 
 
      s := Socket(PF_INET, SOCK_STREAM, IPPROTO_IP); 
      if s = INVALID_SOCKET then 
        Continue; 
 
      ThreadInfo.nRunFlag := 127; 
 
      HostEnt := gethostbyname(PChar(@Config.sIDSAddr[1])); 
      if HostEnt = nil then 
        Continue; 
 
      PInteger(@Name.sin_addr.S_addr)^ := PInteger(HostEnt.h_addr^)^; 
      Name.sin_family := HostEnt.h_addrtype; 
      Name.sin_port := htons(Config.nIDSPort); 
      Name.sin_family := PF_INET; 
 
      ThreadInfo.nRunFlag := 128; 
      if connect(s, Name, SizeOf(Name)) = SOCKET_ERROR then 
      begin 
        nRet := WSAGetLastError; 
 
        closesocket(s); 
        s := INVALID_SOCKET; 
        Continue; 
      end; 
 
      argp := 1; 
      if ioctlsocket(s, FIONBIO, argp) = SOCKET_ERROR then 
      begin 
        closesocket(s); 
        s := INVALID_SOCKET; 
        Continue; 
      end; 
      ThreadInfo.nRunFlag := 129; 
      Config.IDSocket := s; 
      Config.boIDSocketConnected := True; 
      MainOutMessage(format(sIDServerConnected, [Config.sIDSAddr, 
        Config.nIDSPort])); 
    end; 
    readfds.fd_count := 1; 
    readfds.fd_array[0] := s; 
    timeout.tv_sec := 0; 
    timeout.tv_usec := 20; 
    ThreadInfo.nRunFlag := 130; 
    nRet := select(0, @readfds, nil, nil, @timeout); 
    if nRet = SOCKET_ERROR then 
    begin 
      ThreadInfo.nRunFlag := 131; 
      nRet := WSAGetLastError; 
      if nRet = WSAEWOULDBLOCK then 
      begin 
        Sleep(10); 
        Continue; 
      end; 
      ThreadInfo.nRunFlag := 132; 
      nRet := WSAGetLastError; 
      Config.nIDSocketWSAErrCode := nRet - WSABASEERR; 
      Inc(Config.nIDSocketErrorCount); 
      Config.DBSocket := INVALID_SOCKET; 
      Sleep(100); 
      Config.boIDSocketConnected := False; 
      closesocket(s); 
      s := INVALID_SOCKET; 
      Continue; 
    end; 
    boRecvData := True; 
    ThreadInfo.nRunFlag := 133; 
    while (nRet > 0) do 
    begin 
      IDSocketRead(Config); 
      Dec(nRet); 
    end; 
  end; 
  if Config.IDSocket <> INVALID_SOCKET then 
  begin 
    Config.IDSocket := INVALID_SOCKET; 
    Config.boIDSocketConnected := False; 
  end; 
  if s <> INVALID_SOCKET then 
  begin 
    closesocket(s); 
  end; 
end; 
 
procedure IDSocketThread(ThreadInfo: pTThreadInfo); stdcall; 
var 
  nErrorCount       : Integer; 
resourcestring 
  sExceptionMsg     = '[Exception] DBSocketThread ErrorCount = %d'; 
begin 
  nErrorCount := 0; 
  while True do 
  begin 
    try 
      IDSocketProcess(ThreadInfo.Config, ThreadInfo); 
      break; 
    except 
      Inc(nErrorCount); 
      if nErrorCount > 10 then 
        break; 
      MainOutMessage(format(sExceptionMsg, [nErrorCount])); 
    end; 
  end; 
  ExitThread(0); 
end; 
 
 
end.