多端口上的delphi TCP服务器挂起关闭

培曼F.

我使用了多端口TCP服务器来接收一些连接

像这样

procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var
    aByte: Byte;
    i,j , tmBodyFrameLength:integer;
    myThread : tthread;
begin
    if not Assigned( allOfflineStringList ) then
    begin
        allOfflineStringList := TStringlist.Create;
    end;
    allOfflineStringList.Clear;

   case AContext.Binding.Port of
      55000: begin       {offline and image}
              AContext.Connection.IOHandler.ReadBytes(data, 1099, False);
              rowFrame :='';
              for I := 0 to length(data)-1 do
              begin
                rowFrame := rowFrame + (data[i].ToHexString);
              end;
              newFrame := copy( rowFrame , 9 , maxInt );
              allOfflineStringList.Append( newFrame );

              TThread.Synchronize (TThread.CurrentThread,
              procedure ()
              begin
                  Label985.caption := 'Offline : ' + allOfflineStringList.Count.ToString ;
                  //Memo14.Lines.Add( datetimetostr(now) +':'+ newFrame );
                  form2.AbLED601.Tag := DateTimeToUnix(now);
                  form2.AbLED601.Checked := true;
              end);
      end;

      55001: begin             {tm online}
          repeat
              aByte := AContext.Connection.IOHandler.ReadByte;
              if aByte=$C0 then
              begin
                  SDRtmOnlineRowFrame2 := SDRtmOnlineRowFrame;
                  SDRtmOnlineRowFrame := '';
                  TThread.Synchronize (TThread.CurrentThread,
                  procedure ()
                  begin
                      form2.Memo14.Lines.Add('tm:'+ SDRtmOnlineRowFrame2 );
                  end);
              end
              else
              begin
                 SDRtmOnlineRowFrame := SDRtmOnlineRowFrame + aByte.ToHexString;
              end;
          until true;
      end;

      55003: begin      {beacon online}
          repeat
              aByte := AContext.Connection.IOHandler.ReadByte;
              if aByte=$C0 then
              begin
                  SDRtmOnlineBeaconRowFrame2 := SDRtmOnlineBeaconRowFrame;
                  SDRtmOnlineBeaconRowFrame := '';
                  TThread.Synchronize (TThread.CurrentThread,
                  procedure ()
                  begin
                      form2.Memo14.Lines.Add('beacon:'+ SDRtmOnlineBeaconRowFrame2 );
                  end);
              end
              else
              begin
                 SDRtmOnlineBeaconRowFrame := SDRtmOnlineBeaconRowFrame + aByte.ToHexString;
              end;
          until true;
      end;
   end;
 end;

一切正常,但是当我关闭连接时正在接收数据

应用程序将停止通话,并且不再响应!

启用和禁用是这样的:

procedure TForm2.CheckBox6Click(Sender: TObject);
var
  ic:integer;
  allIpList : TStringList;
begin
   AbLED412.Checked := CheckBox6.Checked;

   if CheckBox6.Checked=true then
   begin

      IdTCPServer1.Active := False;
      IdTCPServer1.Bindings.Clear;

      with IdTCPServer1.Bindings.Add do
      begin
        //IP := '192.168.1.5';
        Port := 55000;
      end;

      with IdTCPServer1.Bindings.Add do
      begin
        //IP := '192.168.1.5';
        Port := 55001;
      end;

      with IdTCPServer1.Bindings.Add do
      begin
        //IP := '192.168.1.5';
        Port := 55003;
      end;

      IdTCPServer1.Active := True;
      IdTCPServer1.StartListening;

      TIdStack.IncUsage;
      try
        allIpList := TStringList.Create;
        GStack.AddLocalAddressesToList( allIpList );
        memo14.lines.clear;
        for ic := 0 to allIpList.Count-1 do
        begin
          memo14.lines.Add('Create tcp connection on ip : '+allIpList[ic]+' and port : 55000');
          memo14.lines.Add('Create tcp connection on ip : '+allIpList[ic]+' and port : 55001');
          memo14.lines.Add('Create tcp connection on ip : '+allIpList[ic]+' and port : 55003');
        end;
      finally
        TIdStack.DecUsage;
      end;


   end
   else
   begin
        IdTCPServer1.StopListening;
        IdTCPServer1.Active := False;
        IdTCPServer1.Bindings.Clear;
        memo14.lines.clear;
   end;

end;

当我关闭应用程序时也接收到数据时再次挂起,但发件人断开连接时关闭应用程序也不会造成任何问题

我怎样才能解决这个问题?

雷米·勒博

您的TIdTCPServer.OnExecute处理程序以线程不安全的方式使用多个变量您不能保护它们免受同时访问它们的多个线程的影响,从而导致它们的数据出现争用情况。

但是,更重要的是,您使用TThread.Synchronize()死锁是一个常见的死锁原因,TIdTCPServer因为死锁是一个多线程组件。OnConnectOnDisconnectOnExecute,和OnError事件被称为客户端工作线程的背景下,而不是在主UI线程。TThread.Synchronize()阻塞调用线程,直到主UI线程处理请求为止。停用将TIdTCPServer终止所有正在运行的客户端线程,并等待它们完全终止。因此,如果TThread.Synchronize()阻止主UI线程停用服务器的同时调用客户端线程,则客户端线程正在主UI线程上等待,而主UI线程正在客户端线程上等待-死锁!

您可以通过以下几种方法解决此问题:

  • 避免TThread.Synchronize()在停用服务器时调用说起来容易做起来难,因为在TThread.Synchronize()您决定停用时,您可能已经处于待处理状态TIdTCPServer并且在决定是否打电话时是一个竞赛条件TThread.Synchronize()

  • TIdTCPServer在单独的工作线程中停用,使主UI线程可以自由处理TThread.Synchronize()TThread.Queue()请求。如果您使用aTThread进行停用,则TThread.WaitFor()等待线程终止时,在主UI线程中调用方法将处理Synchronize()/Queue()请求。

  • 使用TThread.Queue()代替TThread.Synchronize(),尤其是在执行客户端线程实际上不需要等待的操作(例如UI更新)时。


另外,在您的中CheckBox6Click()

  • 你不应该打电话TIdTCPServer.StartListening()TIdTCPServer.StopListening()在所有。TIdTCPServer.Active属性setter调用它们内部的你。

  • 您不需要调用TIdStack.IncUsage()TIdStack.DecUsage(),因为TIdTCPServer的构造函数和析构函数会为您调用它们。

  • 你在漏水allIpList,不是Free()并且TIdStack.AddLocalAddressesToList()无论如何都已弃用,您应该TIdStack.GetLocalAddressList()改为使用

尝试这个:

procedure TForm2.CheckBox6Click(Sender: TObject);
var
  ic: integer;
  allIpList : TIdStackLocalAddressList;
begin
  AbLED412.Checked := CheckBox6.Checked;

  if CheckBox6.Checked then
  begin
    IdTCPServer1.Active := False;
    IdTCPServer1.Bindings.Clear;

    with IdTCPServer1.Bindings.Add do
    begin
      //IP := '192.168.1.5';
      Port := 55000;
    end;

    with IdTCPServer1.Bindings.Add do
    begin
      //IP := '192.168.1.5';
      Port := 55001;
    end;

    with IdTCPServer1.Bindings.Add do
    begin
      //IP := '192.168.1.5';
      Port := 55003;
    end;

    IdTCPServer1.Active := True;

    allIpList := TIdStackLocalAddressList.Create;
    try
      GStack.GetLocalAddressesList( allIpList );
      Memo14.Lines.Clear;
      {
      for ic := 0 to IdTCPServer1.Bindings.Count-1 do
      begin
        Memo14.Lines.Add('Create tcp connection on ip : ' + IdTCPServer1.Bindings[ic].IP + ' and port : ' + IntToStr(IdTCPServer1.Bindings[ic].Port));
      end;
      }
      for ic := 0 to allIpList.Count-1 do
      begin
        if allIpList[ic].IPVersion = ID_DEFAULT_IP_VERSION then
        begin
          Memo14.Lines.Add('Create tcp connection on ip : ' + allIpList[ic].IPAddress + ' and port : 55000');
          Memo14.Lines.Add('Create tcp connection on ip : ' + allIpList[ic].IPAddress + ' and port : 55001');
          Memo14.Lines.Add('Create tcp connection on ip : ' + allIpList[ic].IPAddress + ' and port : 55003');
        end;
      end;
    finally
      allIpList.Free;
    end;
  end
  else
  begin
    IdTCPServer1.Active := False;
    IdTCPServer1.Bindings.Clear;
    Memo14.Lines.Clear;
  end;
end;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

NodeJS在多个端口上运行tcp服务器?

来自分类Dev

多端口Netty套接字服务器

来自分类Dev

多线程服务器多端口同时发送文件

来自分类Dev

当关闭端口时,使用套接字检查远程服务器上打开的端口是否挂起,C

来自分类Dev

转:同时在两个不同的端口上运行TCP服务器吗?

来自分类Dev

TCP打孔后打开的端口上可以托管HTTP / HTTPS服务器吗?

来自分类Dev

如何使服务器在多个端口上侦听

来自分类Dev

在每个端口上停止Python localhost服务器

来自分类Dev

TFTP服务器未在定义的端口上侦听

来自分类Dev

无法连接到特定端口上的远程服务器

来自分类Dev

在任意端口上运行apache Web服务器?

来自分类Dev

查找在特定端口上运行的网络中的服务器

来自分类Dev

为什么mysql服务器不接受非本地连接请求,但仍在tcp端口上侦听?

来自分类Dev

MySQL无法启动。[错误]无法启动服务器:在TCP / IP端口上绑定:没有这样的文件或目录

来自分类Dev

节点http服务器即使关闭也仍保留端口8080

来自分类Dev

Ubuntu 16.04服务器端口自行关闭

来自分类Dev

如何关闭CentOS 7服务器上的端口?

来自分类Dev

VNC 服务器端口已关闭

来自分类Dev

串行端口上的TCP / IP

来自分类Dev

NodeJS在创建新服务器之前关闭先前的服务器端口

来自分类Dev

Windows服务器CAL,用于访问TCP端口

来自分类Dev

tcp 服务器未绑定到特定端口

来自分类Dev

在服务器的本地主机上侦听端口是否与在服务器的公共IP地址的端口上侦听相同?

来自分类Dev

如何仅在运行服务器的端口上进行联机端口扫描?

来自分类Dev

如何通过终端识别在远程服务器上的端口上运行的实际服务?

来自分类Dev

客户端意外关闭时,SSH隧道服务器无法关闭侦听端口

来自分类Dev

连接后增强从TCP服务器访问TCP客户端IP地址+端口

来自分类Dev

如何使用Docker在一台服务器的默认端口上运行各种Web服务器?

来自分类Dev

关闭了运行服务器的终端窗口,但是尝试重新运行服务器时,该端口仍在使用中

Related 相关文章

  1. 1

    NodeJS在多个端口上运行tcp服务器?

  2. 2

    多端口Netty套接字服务器

  3. 3

    多线程服务器多端口同时发送文件

  4. 4

    当关闭端口时,使用套接字检查远程服务器上打开的端口是否挂起,C

  5. 5

    转:同时在两个不同的端口上运行TCP服务器吗?

  6. 6

    TCP打孔后打开的端口上可以托管HTTP / HTTPS服务器吗?

  7. 7

    如何使服务器在多个端口上侦听

  8. 8

    在每个端口上停止Python localhost服务器

  9. 9

    TFTP服务器未在定义的端口上侦听

  10. 10

    无法连接到特定端口上的远程服务器

  11. 11

    在任意端口上运行apache Web服务器?

  12. 12

    查找在特定端口上运行的网络中的服务器

  13. 13

    为什么mysql服务器不接受非本地连接请求,但仍在tcp端口上侦听?

  14. 14

    MySQL无法启动。[错误]无法启动服务器:在TCP / IP端口上绑定:没有这样的文件或目录

  15. 15

    节点http服务器即使关闭也仍保留端口8080

  16. 16

    Ubuntu 16.04服务器端口自行关闭

  17. 17

    如何关闭CentOS 7服务器上的端口?

  18. 18

    VNC 服务器端口已关闭

  19. 19

    串行端口上的TCP / IP

  20. 20

    NodeJS在创建新服务器之前关闭先前的服务器端口

  21. 21

    Windows服务器CAL,用于访问TCP端口

  22. 22

    tcp 服务器未绑定到特定端口

  23. 23

    在服务器的本地主机上侦听端口是否与在服务器的公共IP地址的端口上侦听相同?

  24. 24

    如何仅在运行服务器的端口上进行联机端口扫描?

  25. 25

    如何通过终端识别在远程服务器上的端口上运行的实际服务?

  26. 26

    客户端意外关闭时,SSH隧道服务器无法关闭侦听端口

  27. 27

    连接后增强从TCP服务器访问TCP客户端IP地址+端口

  28. 28

    如何使用Docker在一台服务器的默认端口上运行各种Web服务器?

  29. 29

    关闭了运行服务器的终端窗口,但是尝试重新运行服务器时,该端口仍在使用中

热门标签

归档