unit UnitSocketCallingHandler; interface uses Classes, SysUtils, ScktComp, HisPrivate, HisPublic, Db, DBTables, IniFiles, Forms, FileCtrl, RttiHelper; type TSocketCallingHandler = class private FsocketList: TTypeList; function ConnectServer(var outMsg: string): Boolean; public constructor Create; destructor Destroy; override; class function InitSocketCallingHandlerUnit(var outMsg: string): Boolean; class function IsEnableSocketCalling: Boolean; function IsSocketServerConnected: Boolean; function Call(callMsg: string): Boolean; function CallByHzbrId(hzbrid: string; var outMsg: string): Boolean; class procedure LogInfo(content: string); class procedure LogErr(content: string); procedure OnSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); end; var SocketCallingHandler: TSocketCallingHandler = nil; implementation uses UnitDBHelper, uuAdd; var FIsEnableSocketCalling: Boolean = False; FHasInitUnited: Boolean = False; { TSocketCallingHandler } procedure SaveTxt_Log(pathname, fileName, content: string);//保存文本日志文件 追加。 var lvdate, lvtime, lv_FileTitle, lvFileName, lvLogfile: string; //当天日期,时间,文件名 pMyFile: textFile; begin lvdate := FormatDateTime('YYYY.MM.DD', Now); lvtime := FormatDateTime('HH:NN:SS ZZZ', Now); lvLogfile := extractfilepath(Application.ExeName) + '\' + pathname + '\' + lvdate; try if not Directoryexists(lvLogfile) then ForceDirectories(lvLogfile); lv_FileTitle := fileName; lvFileName := lvLogfile + '\' + lv_FileTitle + '.txt'; AssignFile(pMyFile, lvFileName); if FileExists(lvFileName) = false then ReWrite(pMyFile) else Append(pMyFile); WriteLn(pMyFile, ''); WriteLn(pMyFile, lvdate + ' ' + lvtime + ': ' + content); CloseFile(pMyFile); except on e: exception do begin CloseFile(pMyFile); exit; end; end; end; function TSocketCallingHandler.Call(callMsg: string): Boolean; var outMsg: string; i: Integer; tmpSocket: TClientSocket; ip: string; port: Integer; begin Result := ConnectServer(outMsg); LogInfo('需要同时叫号的叫号显示屏数量' +IntToStr(FsocketList.Instances.Count)); for i := 0 to FsocketList.Instances.Count - 1 do begin tmpSocket := TClientSocket(FSocketList.Instances[i]); try ip := tmpSocket.Address; port := tmpSocket.Port; LogInfo('socket ip=' + ip + ' port=' + inttostr(port) + ' ' + callMsg); tmpSocket.Socket.SendText(UTF8Encode(trim(callMsg))); LogInfo(ip + ' socket over'); Result := True; except on e: Exception do begin Result := False; end; end; end; end; function TSocketCallingHandler.CallByHzbrId(hzbrid: string; var outMsg: string): Boolean; var ls_request: string; begin Result := False; // if not SocketCallingHandler.FClientSocket.Active then // if not ConnectServer(outMsg) then // Exit; if TSocketCallingHandler.IsEnableSocketCalling then begin with DBHelper.Query('select GHH000,XM0000,HZCKMC1 from VW_YS_HZBR00 where GHMZSJ=to_char(sysdate,''yyyymmdd'') and ID0000=:ID0000', vararrayof([hzbrid])) do try if IsEmpty then begin outMsg := '未查到病人候诊信息' + hzbrid; Exit; end; ls_request := '' + hzbrid + '' + trim(fieldbyname('GHH000').asstring) + '' + '请' + trim(fieldbyname('XM0000').asstring) + '到' + trim(fieldbyname('HZCKMC1').asstring) + '就诊'; if not SocketCallingHandler.Call(ls_request) then begin outMsg := 'socket发送请求失败'; Exit; end; Result := True; finally Free; end; end; end; function TSocketCallingHandler.ConnectServer(var outMsg: string): Boolean; var ip: string; port: Integer; i: Integer; tmpSocket: TClientSocket; resMsg: string; begin Result := True; outMsg := ''; for i := 0 to FsocketList.Instances.Count - 1 do begin try tmpSocket := TClientSocket(FsocketList.Instances[i]); if @tmpSocket.OnError = nil then tmpSocket.OnError := OnSocketError; ip := tmpSocket.Address; port := tmpSocket.Port; //先接收一下来自于服务端的消息 不为空的有两种情况 1是第一次连接成功服务端会返回成功报文 2是断开重连后的错误报文 都记录下来 if tmpSocket.Active then begin resMsg := Utf8Decode(tmpSocket.Socket.ReceiveText); if trim(resMsg) <> '' then begin LogInfo('Socket叫号服务器IP' + ip + 'Port' + IntToStr(port) + '返回1: ' + resMsg); end; end; LogInfo('正在连接Socket叫号服务器IP' + ip + 'Port' + IntToStr(port)); tmpSocket.Active := True;; if tmpSocket.Active then begin resMsg := Utf8Decode(tmpSocket.Socket.ReceiveText); if trim(resMsg) <> '' then begin LogInfo('Socket叫号服务器IP' + ip + 'Port' + IntToStr(port) + '返回2: ' + resMsg); end; LogInfo('已连接Socket叫号服务器IP' + ip + 'Port' + IntToStr(port)); end else begin LogInfo('连接Socket叫号服务器IP' + ip + 'Port' + IntToStr(port) +'失败,请确认地址和端口'); end; except on e: Exception do begin Result := False; outMsg := outMsg + '连接显示屏失败 IP' + ip + ' Port' + IntToStr(port) + #10#13; Continue; end; end; end; Result := outMsg = ''; end; constructor TSocketCallingHandler.Create; begin FsocketList := TTypeList.Create('TClientSocket'); end; destructor TSocketCallingHandler.Destroy; begin inherited; FsocketList.Free; end; class function TSocketCallingHandler.InitSocketCallingHandlerUnit(var outMsg: string): Boolean; var tmpSql: string; ip: string; port: Integer; tmpSocket: TClientSocket; isSocketOn: Integer; i: Integer; begin Result := True; LogInfo('初始化Socket叫号单元'); if FHasInitUnited then Exit; FIsEnableSocketCalling := LowerCase(Trim(DBHelper.GetValueAsString('select value0 from xt_xtcs00 where name00 =' + QuotedStr('YS_SFQYBRSOCKETJZFW')))) = 'y'; if not FIsEnableSocketCalling then begin LogInfo('Socket叫号不启用'); Exit; end; ip := ''; port := 0; //通过科室获取叫号连接到哪一台服务器 tmpSql := 'select PORT00,FWIP00 from XT_ZSJHIP where DLRQ00=to_char(sysdate,''yyyymmdd'') ' + ' and instr('',''||KSBH00||'','','',''||' + inttostr(giUserDeptID) + '||'','')>0 and TCRQ00 is null'; with DBHelper.Query(tmpSql) do try if not IsEmpty then begin ip := FieldByName('FWIP00').AsString; port := FieldByName('PORT00').AsInteger; end; finally Free; end; //如果Login.ini 有配置 则优先ini with TIniFile.Create(ExtractFilePath(Application.ExeName) + 'Login.ini') do try isSocketOn := ReadInteger('SocketCalling', 'SocketOn', -1); if isSocketOn = 1 then begin if not Assigned(SocketCallingHandler) then SocketCallingHandler := TSocketCallingHandler.Create; for i := 0 to 5 do begin ip := ''; port := -1; if i = 0 then begin port := ReadInteger('SocketCalling', 'SocketCallingPort', -1); ip := ReadString('SocketCalling', 'SocketCallingIp', 'N'); end else begin port := ReadInteger('SocketCalling', 'SocketCallingPort' + IntToStr(i), -1); ip := ReadString('SocketCalling', 'SocketCallingIp' + IntToStr(i), 'N'); end; if (ip <> 'N') and (port <> -1) then begin tmpSocket := TClientSocket.Create(Application); tmpSocket.Address := ip; tmpSocket.Port := port; SocketCallingHandler.FsocketList.Instances.Add(tmpSocket); end; end; end else if isSocketOn = 0 then begin LogInfo('本地配置文件SocketOn为0,Socket叫号不启用'); FIsEnableSocketCalling := False; FHasInitUnited := False; Exit; end else begin //否则按表数据的端口IP来连 if (ip <> '') and (port > 0) then begin tmpSocket := TClientSocket.Create(Application); tmpSocket.Address := ip; tmpSocket.Port := port; SocketCallingHandler.FsocketList.Instances.Add(tmpSocket); end else begin LogInfo('未正确获取叫号服务器IP和端口,socket叫号不启用'); outMsg := '必须设置Socket叫号IP地址和端口, 否则叫号功能不生效'; FIsEnableSocketCalling := False; FHasInitUnited := False; Exit; end; end; finally Free; end; FHasInitUnited := True; Result := SocketCallingHandler.ConnectServer(outMsg); end; class function TSocketCallingHandler.IsEnableSocketCalling: Boolean; begin Result := FIsEnableSocketCalling; end; function TSocketCallingHandler.IsSocketServerConnected: Boolean; begin // Result := FClientSocket.Active; end; class procedure TSocketCallingHandler.LogErr(content: string); begin LogInfo(content); SaveTxt_Log('医生护士站日志', 'socket叫号Error', content); end; class procedure TSocketCallingHandler.LogInfo(content: string); begin SaveTxt_Log('医生护士站日志', 'socket叫号Info', content); end; procedure TSocketCallingHandler.OnSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin SaveTxt_Log('医生护士站日志', 'socket叫号Info', '叫号服务器连接异常'+ inttostr(ErrorCode)); // showmessage('叫号服务器连接异常'+ inttostr(ErrorCode)); ErrorCode := 0; end; initialization finalization if Assigned(SocketCallingHandler) then FreeAndNil(SocketCallingHandler); end.