delphi 中的  serversocket 问题,急等,在线寻求帮助 用的是 serversocket控件做的一个 “心跳监控”软件 ,用的是长连接模式“stNonBlocking”,
 程序一打开,还能监听540多个客户端,属于正常情况,但是在运行20分钟后,就发现 在线的客户端只有
200个左右,有时候甚至只有几十个,把监听服务停掉,然后在启动监听服务又能监听到 500 多个,过20多
分钟过后,又是只能监听到一部分,请问,这个事怎么回事呢?在线等待,急用呀。。

解决方案 »

  1.   

    //启动服务器方法
    function  TForm_ShiPing.Start_ser():String;
    begin     //验证端口号是否正确
     try
          StrToInt(EditProt.Text);
     except
          MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:', Now)+'【端口填写错误,请重新填写】');
          EditProt.SetFocus;
          Exit;
     end; //启动服务
     try        ServerSocket_ser.Port := StrToInt(EditProt.Text);
        ServerSocket_ser.Active := true;
        MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【启动成功】');    Label_djs.Caption := Edit_time.Text;
        
        But_start.Enabled := false;
        EditProt.Enabled := false;
        Edit_time.Enabled := false;
        But_stop.Enabled := true;
         //启动计时器
         Timer_cl.Enabled := true;
         
         //初始化计数器数据
         timeNum := StrToInt(Edit_time.Text);
         //初始化接收到的心跳数据
         reNum := 0;
         //初始化已处理的心跳数据
         proNum := 0;    //创建TstringList
        strDataCl := TStringList.Create;
        //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【启动成功】','0'); except
        MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【启动失败】');    //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【启动失败】','0');    Exit;
     end;
    end;ServerSocket 控件这是如下:
    Action -> false
    Port -> 8375
    ServerType -> stNonBlocking
    Service -> 
    Tag -> 0
    ThreadCacheSize -> 10 
    下面的服务器都是在1分钟发一个心跳包上来,然后我就把收到的心跳包解析后更新到数据库,
    现在就出现了运行一会儿 就接收不到大部分心跳,其中说明一点的是,500多个服务器心跳全部正常
    请问这个事什么问题呢?
    希望高手帮忙看看,在线等待。。急用
      

  2.   

    以下是全部代码 ,请各位高手帮忙看看,多谢了unit ShiPing_ser;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ScktComp, ExtCtrls, ADODB, DB, ComCtrls,
      IdBaseComponent, IdComponent, IdTCPServer, IdTCPConnection,
      IdSimpleServer;type
      TForm_ShiPing = class(TForm)
        Label1: TLabel;
        EditProt: TEdit;
        MemoMsg: TMemo;
        ServerSocket_ser: TServerSocket;
        Timer_cl: TTimer;
        GroupBox1: TGroupBox;
        Label_djs: TLabel;
        ADOConnection_sql: TADOConnection;
        GroupBox2: TGroupBox;
        Label_Cl: TLabel;
        StatusBar_state: TStatusBar;
        Label_dd: TLabel;
        Label_clz: TLabel;
        Label3: TLabel;
        ADOStoredProc_sql: TADOStoredProc;
        Edit_time: TEdit;
        Label2: TLabel;
        But_start: TButton;
        But_stop: TButton;
        Timer_server: TTimer;
        IdTCPServer_server: TIdTCPServer;
        procedure FormCreate(Sender: TObject);
        procedure But_stopClick(Sender: TObject);
        procedure ServerSocket_serClientConnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ServerSocket_serClientDisconnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ServerSocket_serClientRead(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure Timer_clTimer(Sender: TObject);
        procedure But_startClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure ServerSocket_serClientError(Sender: TObject;
          Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
          var ErrorCode: Integer);
        procedure Timer_serverTimer(Sender: TObject);
        procedure IdTCPServer_serverExecute(AThread: TIdPeerThread);
        procedure IdTCPServer_serverConnect(AThread: TIdPeerThread);
        procedure IdTCPServer_serverDisconnect(AThread: TIdPeerThread);
          private
        { Private declarations }
         function  Data_Cl():string;
         function  Start_ser():String;
         function  Indy_Start_ser():String;
         function IntToBinaryStr(TheVal: LongInt): string;
      public
        
        { Public declarations }
      end;var
      Form_ShiPing: TForm_ShiPing;
      //记录一定时间内取得的sn
      strDataCl : TStringList;
      //倒计时记录器
      timeNum : Integer;
      //接收到的心跳数据
      reNum : Integer;
      //已处理的心跳数据
      proNum : Integer;
    implementationuses DateUtils,ProgLog;{$R *.dfm}
    procedure TForm_ShiPing.FormCreate(Sender: TObject);
    begin
       
      //清空文本
      MemoMsg.Clear;
       //启动服务器
       Start_ser();
      // Indy_Start_ser();
    end;procedure TForm_ShiPing.But_stopClick(Sender: TObject);
    begin
      //停止服务器
        ServerSocket_ser.Active := false;
        MemoMsg.Lines.Add(FormatDateTime('HH时:',Now)+'【服务器停止成功】');
        But_start.Enabled := true;
        But_stop.Enabled := false;
        EditProt.Enabled := true;
        Edit_time.Enabled := true;
        //关闭计时器
        Timer_cl.Enabled := false;
         //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【服务器停止成功】','0');
    end;procedure TForm_ShiPing.ServerSocket_serClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
        try
           //客户端连接后,实时统计客户端个数
         //  Form_ShiPing.Caption := '视频心跳监控----'+IntToStr(ServerSocket_ser.Socket.ActiveConnections)
           //                         +'个客户端';
       except
        // MemoMsg.Lines.Add('conn:err');
         end;
    end;procedure TForm_ShiPing.ServerSocket_serClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      //断开连接统计客户端
      //Form_ShiPing.Caption := '视频心跳监控----'+IntToStr(ServerSocket_ser.Socket.ActiveConnections-1)
                                  //  +'个客户端';
    end;
      

  3.   

    procedure TForm_ShiPing.ServerSocket_serClientRead(Sender: TObject;
      Socket: TCustomWinSocket);var
       //计数器
       num : Integer;
       //循环变量
       i : Integer;
        //存储接收到的数据
       dataBuf : array[0..48] of Byte;
       //存储转换后的sn
       strData : String;
       //存储转换后的状态
       strState : String;
       //临时变量
       strTemps : string;
       strTempYzState : Integer;
       StrTep : String;
    begin  try      Socket.ReceiveBuf(dataBuf,49);
          strTemps := chr(dataBuf[0])+'';
          num :=  Integer(dataBuf[4]);
      except
      end;
        if  strTemps = '#' then
         begin
         //读取客户端跳上来的数据
          for i:=5  to num+4 do
          begin
              try            if i <= num  then
                    begin
                        strData := strData+chr(dataBuf[i]);
                    end
                 else
                    begin
                         strTempYzState := strTempYzState+Integer(dataBuf[i]);
                    end
              except
             end;
          end;         StrTep := IntToBinaryStr(strTempYzState);
           if Length(StrTep) = 1 then
              begin
                 StrTep := '000'+ StrTep;
              end
           else if Length(StrTep) = 2 then
              begin
                 StrTep := '00'+ StrTep;
              end
           else if Length(StrTep) = 3 then
              begin
                 StrTep := '0'+ StrTep;
              end;
           
            strState := StrTep;
          //取得的sn写入TstringList
          strDataCl.Add(strData+':'+strState+';');
          //实时记录最新接收数据个数
         // reNum :=  reNum+1;       //检测窗体当达到500条时执行清空
           if MemoMsg.Lines.Count > 500 then
             begin
               MemoMsg.Clear;
             end;       //再窗体中显示数据
           MemoMsg.Lines.Add(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort)+ '【SN】'+strData+'【状态】'+strState);       //写入日志文件
          //programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort)+ '个数:'+IntToStr(num)+'   【SN】'+strData+'【状态】'+strState,'0');       //状态栏显示数据
           //StatusBar_state.Panels[0].Text :='状态:       已收到数据:'+IntToStr(reNum)+' 条       已处理数据:'+IntToStr(proNum)+' 条   ';
          end
        else
           begin
              //不正常接入写入日志文件
              programLog(FormatDateTime('【YY-MM-DD HH:NN:SS】 ', Now)+' 不正常数据接入:'+Socket.RemoteAddress,'0');       end;
    end;procedure TForm_ShiPing.Timer_clTimer(Sender: TObject);
    var
       //临时测试变量
        st :string;
    begin
      if timeNum = 0 then
         begin
          Timer_cl.Enabled := false;
          Label_clz.Color := clLime;      //调用处理数据方法
          st := Data_Cl();      //处理完成,更改状态
           if st = '0' then
            begin
               Label_dd.Color := clLime;
               Label_clz.Color := clred;
            end;      Timer_cl.Enabled := true;
          timeNum := StrToInt(Edit_time.Text);     end
      else
         begin
         timeNum := timeNum-1;
         end;
      if timeNum < 10 then
         begin
         Label_djs.Caption := '0'+IntToStr(timeNum);
         end
      else
         begin
         Label_djs.Caption := IntToStr(timeNum);
         end;end;
    //数据处理函数
    function  TForm_ShiPing.Data_Cl():String;
    var
       strData_Ls : TStringList;
       //循环变量
       i : Integer;
       //循环变量
       k : Integer;
       //统计数组个数
       strNum : Integer;
       //临时变量
       strTemp :String;
    begin
        strData_Ls := TStringList.Create;
        strNum := strDataCl.Count;    //判断list里面是否有数据,有则执行
        if strNum <> 0 then
          begin
             
             for i:=0 To strNum-1 do
                begin
                  strData_Ls.Add(strDataCl[i]);
                end;         //清空记录数据
             strDataCl.Clear;
             
             //写入日志文件
             programLog('*******************************','1');
              for k:=0 To strData_Ls.Count-1 do
                 begin
                   strTemp := strTemp+strData_Ls[k];
                   programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+strData_Ls[k],'1');
                 end;        try           ADOStoredProc_sql.Parameters.ParamByName('thingsStr').Value := strTemp;
               ADOStoredProc_sql.ExecProc;           programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'  执行存储过程成功','1');
               programLog('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@','1');           //统计成功更新数据个数
               // proNum := proNum+strData_Ls.Count;
                //状态栏显示数据
               //StatusBar_state.Panels[0].Text :='状态:       已收到数据:'+IntToStr(reNum)+' 条       已处理数据:'+IntToStr(proNum)+' 条   ';        except
               
               programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'执行存储过程失败','1');
               programLog('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@','1');
            end;
            ADOStoredProc_sql.Active := false;      end;
        Result := '0';    
    end;//启动服务器方法
    function  TForm_ShiPing.Start_ser():String;
    begin     //验证端口号是否正确
     try
          StrToInt(EditProt.Text);
     except
          MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:', Now)+'【端口填写错误,请重新填写】');
          EditProt.SetFocus;
          Exit;
     end; //启动服务
     try    ServerSocket_ser.Port := StrToInt(EditProt.Text);
        ServerSocket_ser.Active := true;
        MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【启动成功】');    Label_djs.Caption := Edit_time.Text;
        
        But_start.Enabled := false;
        EditProt.Enabled := false;
        Edit_time.Enabled := false;
        But_stop.Enabled := true;
         //启动计时器
         Timer_cl.Enabled := true;
         
         //初始化计数器数据
         timeNum := StrToInt(Edit_time.Text);
         //初始化接收到的心跳数据
         reNum := 0;
         //初始化已处理的心跳数据
         proNum := 0;    //创建TstringList
        strDataCl := TStringList.Create;
        //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【启动成功】','0'); except
        MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【启动失败】');    //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【启动失败】','0');    Exit;
     end;
    end;
    //IndyServer服务启动
    function  TForm_ShiPing.Indy_Start_ser():String;
    begin
        try      IdTCPServer_server.DefaultPort := StrToInt(EditProt.Text);
          IdTCPServer_server.Active := true;
          MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【启动成功】');
        except
           ShowMessage('启动错误');
           Exit;
        end;end;
    procedure TForm_ShiPing.But_startClick(Sender: TObject);
    begin
      //启动服务器
       Start_ser();
       
    end;procedure TForm_ShiPing.FormClose(Sender: TObject;
      var Action: TCloseAction);
    begin
        //停止服务器
        ServerSocket_ser.Active := false;
        MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'【服务器停止成功】');
        But_start.Enabled := true;
        But_stop.Enabled := false;
        EditProt.Enabled := true;
        Edit_time.Enabled := true;
        //关闭计时器
        Timer_cl.Enabled := false;
         //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【服务器停止成功】','0');
    end;
    //int型转换成二进制
    function TForm_ShiPing.IntToBinaryStr(TheVal: LongInt): string;
    var
    counter: LongInt;
    begin
    if TheVal = 0 then begin
        result := '0';
        exit;
    end;
    result := '';
    counter := $80000000;
    while ((counter and TheVal) = 0) do begin
        counter := counter shr 1;
        if (counter = 0) then break;
    end;
    while counter > 0 do begin
        if (counter and TheVal) = 0 then result := result + '0'
        else result := result + '1';
        counter := counter shr 1;
    end;
    end;
    procedure TForm_ShiPing.ServerSocket_serClientError(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    begin
          ErrorCode := 0;
          programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【10053 错误】','0');
    end;
      

  4.   

    procedure TForm_ShiPing.Timer_serverTimer(Sender: TObject);
    begin   //停止服务器
        ServerSocket_ser.Active := false;
        MemoMsg.Lines.Add(FormatDateTime('HH时:',Now)+'【服务器停止成功】');
        But_start.Enabled := true;
        But_stop.Enabled := false;
        EditProt.Enabled := true;
        Edit_time.Enabled := true;
        //关闭计时器
        Timer_cl.Enabled := false;
         //写入日志文件
        programLog(FormatDateTime('[YY-MM-DD HH:NN:SS]  ', Now)+'【服务器停止成功】','0');    //清空状态框
        MemoMsg.Clear;    //启动服务器
       Start_ser();
    end;procedure TForm_ShiPing.IdTCPServer_serverExecute(AThread: TIdPeerThread);
    begin
       // MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'收到数据');
    end;procedure TForm_ShiPing.IdTCPServer_serverConnect(AThread: TIdPeerThread);
    begin
          MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'有连接');
    end;procedure TForm_ShiPing.IdTCPServer_serverDisconnect(
      AThread: TIdPeerThread);
    begin
          MemoMsg.Lines.Add(FormatDateTime('HH时NN分SS秒:',Now)+'断开连接');
    end;end.
      

  5.   

      ServerSocket.ThreadCacheSize 最大值能接收多少客户端?
    64,300,1000,2000??
      [email protected]  唐姊