Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何让TIdTCPServer在每次收到消息时都进行回复?_Delphi_Indy - Fatal编程技术网

Delphi 如何让TIdTCPServer在每次收到消息时都进行回复?

Delphi 如何让TIdTCPServer在每次收到消息时都进行回复?,delphi,indy,Delphi,Indy,我正在学习如何使用HL7、IdTCPClient和IdTCPServer。收到HL7消息后,我只收到服务器对第一条消息的确认回复。但在此之后,将收到消息,但不会发送确认回复。它挂起在AContext.Connection.IOHandler.WriteLn。如何让IdTCPServer为收到的每封邮件发送确认回复?非常感谢您的意见。以下是服务器端代码onExcute: procedure THL7DM.IdTCPServer1Execute(AContext: TIdContext); Fu

我正在学习如何使用HL7、IdTCPClient和IdTCPServer。收到HL7消息后,我只收到服务器对第一条消息的确认回复。但在此之后,将收到消息,但不会发送确认回复。它挂起在AContext.Connection.IOHandler.WriteLn。如何让IdTCPServer为收到的每封邮件发送确认回复?非常感谢您的意见。以下是服务器端代码onExcute:

procedure THL7DM.IdTCPServer1Execute(AContext: TIdContext);
  Function AcknowledgementMessage(HL7_msg: string): string;
  var
    s: TStrings;
    MSA: TMSASegment;
    MSH: TMSHSegment;

  begin
    result := '';
    MSH := TMSHSegment.Create(HL7_msg); {HL7 MSH Segment}
    MSA := TMSASegment.Create(''); {HL7 MSA Segment}
    s := TStringList.Create;
    try

      MSH.Accept_Acknowledgment_Type_15 := 'AA';

      MSA.Acknowledgment_Code_18 := 'AA';
      MSH.Sending_Facility_4 := 'AEdge Lab';
      MSH.Message_Type_9 := 'ACK';
      MSA.Message_Waiting_Number_1827 := DateTimeToStr(now);

      s.Text := MSH.ToString + #13 + #10 + 'MSA' + '|' + MSA.ToString;
      s.Text := #11 + s.Text + #28 + #13;
      result := s.Text;
    finally
      MSA.Free;
      MSH.Free;
      s.Free;
    end;
  end;

var
  MsgStrings: TStrings;
  s: string;
  msg: string;
begin
  MsgStrings := TStringList.Create;
  s := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_OSDefault());
  try
    MsgStrings.Text := StrEscapedToString(s);
    Form2.Memo3.Text := TRegEx.Replace(MsgStrings.Text, #11 + '|' + #28, '');
    msg := AcknowledgementMessage(Form2.Memo3.Text);
     if TRegEx.IsMatch(msg, #28#13) = True then
==>   AContext.Connection.IOHandler.WriteLn(StrStringToEscaped(msg),
      IndyTextEncoding_OSDefault());
   if TRegEx.IsMatch(MsgStrings.Text, #11) = True then
    SaveMessageToDatabase(MsgStrings);
  finally
    MsgStrings.Free;
  end;
end;
以下是发送消息的客户端:

procedure TForm2.BitBtn1Click(Sender: TObject);
var
  LLine: String;
  I: Integer;
  s: string;

begin

  // wrapping for HL7
  LLine := #11 + Memo1.Text + #28 + #13;

  if Receiving_System_Accepts_Escaped_Strings then

    HL7DM.IdTCPClient1.IOHandler.WriteLn(StrStringToEscaped(LLine),
      IndyTextEncoding_OSDefault())
  else
    HL7DM.IdTCPClient1.IOHandler.WriteLn(LLine, IndyTextEncoding_OSDefault());

  if Assigned(ACKReplyHandler) = False then
  begin
    ACKReplyHandler := TACK_MsgHandlingThread.Create;
    //This will handle incoming HL7 ACK replies
  end;

end;
TACK_MsgHandlingThread如下所示:

procedure TACK_MsgHandlingThread.Execute;
begin
  HandleACK_Replies;
end;

procedure TACK_MsgHandlingThread.HandleACK_Replies;
var
  s: string;
begin
  s := (HL7DM.IdTCPClient1.IOHandler.ReadLn(IndyTextEncoding_UTF8));
 // ShowMessage(s);
  s := StrEscapedToString(s);
  s := TRegEx.Replace(s, #11, '');
  s := TRegEx.Replace(s, #28#13#10, '');

  Form2.Memo4.Clear;

  Form2.Memo4.Text := (s);
end;

TIdIOHandler.WriteLn()
可以阻止的唯一方法是,如果接收方未读取已发送的数据,则会导致其入站缓冲区填满,并阻止发送方发送更多数据。这是因为您的
TACK\u MsgHandlingThread.Execute()
方法只读取一个传入的回复,然后在
Execute()
退出时终止线程,因此它停止读取后续回复。在线程的生命周期内,您需要在循环中运行
HandleACK\u repress()
的逻辑,为每个发送的回复调用
TIdIOHandler.ReadLn()
,直到套接字关闭和/或线程终止

另外,
IndyTextEncoding\u OSDefault
不能跨机器边界移植。但更重要的是,您在客户端使用的是
IndyTextEncoding\u UTF8
。您需要在两侧使用相同的编码,否则您将面临数据丢失的风险


此外,您的服务器正在访问
Memo3
,而您的客户端正在访问
Memo4
,而根本不与各自的UI线程同步。这是非常危险的。VCL和FMX框架不是线程安全的(大多数UI框架都不是),因此从UI线程外部访问UI控件时必须同步。

非常感谢您的输入Lebeau先生。自从我开始学习以来,我一直在使用备忘录来查看WriteLn和ReadLn的内容,服务器和客户端都在一个应用程序中。我还尝试使用两个虚拟机,连接正常,收到消息。我使用JclStrings strStrStringToeScaped和StrEscapedToString函数将多行转义为一个字符串。这太棒了。非常感谢你!!