我已经写过一个这样的东西,但是不好用常常出现问题,而且出现的问题比较严重的是会不能采集数据。
我采用的是windows的服务形式编写的程序。出现的错误不外乎两类
1.事件 ID ( 0 )的描述(在资源( MyServer.exe )中)无法找到。本地计算机可能没有必要的注册信息或消息 DLL 文件来从远端计算机显示消息。部分事件包含了下列信息: List index out of bounds (27).
2.事件 ID ( 0 )的描述(在资源( MyServer.exe )中)无法找到。本地计算机可能没有必要的注册信息或消息 DLL 文件来从远端计算机显示消息。部分事件包含了下列信息: Access violation at address 00403D71 in module 'BGServer.exe'. Read of address 01004338.
出第一个的时候还可以正常工作,第二个好像不行了像崩溃了似的。我的软件的要求是通过IdTcpServer作服务器端
在程序启动的时候有一个设备列表
当有设备连接服务器的时候通过查询列表
知道那个终端连接的
最后就是数据链路维护,当发现30秒连接的客户端没有数据强制断开连接
不知道那个高人有这样的构架,让小弟了解了解我的方式是仿照了delphi的例子作的
Clients:Tlist来维护连接
但就是这个clients出问题
在当30秒的时候,我通过循环访问每个clients的元素,发现是那个
Athread,然后断开连接,但是有时候常常出现错误。痛苦!!Delphi是不是不能做这样的实时通讯系统呢。

解决方案 »

  1.   

    TListList index out of bounds (27).Access violation at address 00403D71 in module 'BGServer.exe'. Read of address 01004338.==================别说DELPHI不行,是你自己的问题!
    很可能出在:你删除了Clients中的节点后又访问了它(第一个错误)
    或是你在List的Item里记录的线程已经结束,但你又访问了它(第二个错误)
      

  2.   

    和我这个软件差不多,你看看
    http://community.csdn.net/Expert/topic/3197/3197739.xml?temp=.6519281
    要是对上号,那咱再联系
      

  3.   

    Indy没问题的,你用得不好的原因哦明显就是TList访问越界http://lysoft.7u7.net
      

  4.   

    各位老大
    indy是没有
    不过Tlist有点不好控制
    我曾经试图多次更改这个问题
    用了很多方法,不过就是解决不了
    如何控制Tlist的访问越界呢
    我看到的Chat的例子,就是这样,而且也会出现
    越界现象的to猛禽
    我的list的item里面记录的线程已经结束时什么意思呢你在List的Item里记录的线程已经结束,但你又访问了它(第二个错误)楼上各位大虾帮忙给我指点一二,小弟将代码贴在下面了
    type
    TSimpleClient = class(TObject)
        Thread: TIdPeerThread;
        DNS:string;
        port:longint;
        name:string;
        delete:boolean;  
        data:integer;
        keep_s:integer;
        newon:boolean;
        FrameNumber:Smallint;
        comstruct:Tcomstruct;
        ms_buf:string;
        Err:array[1..9] of byte;              
    end;procedure TServiceGprs.tcpserverConnect(AThread: TIdPeerThread);
    var Client: TSimpleClient;
    begin
    { try
      check_DNS(athread);
      except
            ;
      end; }
      Client := TSimpleClient.Create;
      client.FrameNumber:=-1;
     // client.Mslist.Create;
      client.delete:=false;
      { Assign its default values }
      { Assign the thread to it for ease in finding }
      client.DNS:=Athread.Connection.Socket.Binding.IP;
      client.port:=Athread.Connection.Socket.Binding.Port;  Client.Thread := AThread;
      { Assign it to the thread so we can identify it later }
      AThread.Data := Client;
      { Add it to the clients list }
      Clients.Add(Client);
      client.newon:=true;
    end;procedure TServiceGprs.tcpserverDisconnect(AThread: TIdPeerThread);
    var
      Client: TSimpleClient;
    begin
    //athread.Connection.Socket.Binding.PeerPort; //ip
    {Retrieve Client Record from Data pointer }
      Try
      Client:=AThread.Data as Tsimpleclient;
      client.delete:=true;
      finally
      begin
      {$IFDEF Test_disconnect_process}
        writelog('一个连接断开 client.name:"'+client.name+'"(如果为空为无连接)'); 
      {$ENDIF}
      AThread.Data := nil;
      end;
      end;
    end;
    procedure TServiceGprs.tcpserverExecute(AThread: TIdPeerThread);
    var
        msg:String;
        Client: TSimpleClient;
        len:Smallint;
        ms_buf_len:word;
      // i:integer;str:STRING;mytextfile:textfile;
    begin
    try
    begin
          Msg:= athread.Connection.CurrentReadBuffer;
          Client := AThread.Data as TSimpleClient;
          Client.ms_buf:=Client.ms_buf+msg;
                ms_buf_len:=length(Client.ms_buf);
                if ms_buf_len>=6 then
                  begin
                    len:=Ulenchk(ord(Client.ms_buf[len_exc]),ord(Client.ms_buf[len_exc+1]));
                    if (len>=0) and (len<=512) then
                      begin
                            if len<=ms_buf_len-con_len then
                                    begin
                                     recv_chk(copy(Client.ms_buf,1,len+con_len),client);
                                    end;
                            if len=ms_buf_len-con_len then
                                    begin
                                    Client.ms_buf:='';
                                    end;
                            if len<ms_buf_len-con_len then
                                    Client.ms_buf:=copy(Client.ms_buf,len+con_len+1,ms_buf_len-len-con_len)
                      end
                    else
                      begin
                           Client.ms_buf:='';
                      end;
                  end;
                end;
              except
              begin
              {$IFDEF Test_receive}
                writelog('Clients_ms_buf error'+client.name);
              {$ENDIF}
              end;
            end;
           // }
    end;procedure TServiceGprs.client_keepTimer(Sender: TObject);
    var count,index:integer;
      Client: TSimpleClient;
      list:Tlist;
    begintry
    list:=tcpserver.Threads.LockList;
    count:=clients.Count;
    if count<>0 then
      begin
        if list.count=0 then
          begin
          inc(CclearFlag);
          if (CclearFlag>3) then
            begin
              clients.Clear;
              CclearFlag:=0;
            end;
          end;
      end;
    finally
     tcpserver.Threads.UnlockList;
    end;for index:=count-1 downto 0  do
    begin
    try
    Client := Clients.Items[index];
    if not client.delete then
            begin
            if not Assigned(Client) then
                    begin
                    {$IFDEF Test_Client_keep}
                    writelog('(侦测到client=nil if not Assigned(Client) then) delete'+client.name);
                    {$ENDIF}
                    Clients.Delete(index);
                    end
            else
                    begin
                    inc(client.keep_s);
                    if (client.keep_s>keep_counts) then
                      begin                    if not Client.Thread.Terminated then
                        begin
                        try
                          Begin
                          {$IFDEF Test_Client_keep}
                          writelog('(当连接'+inttostr(keep_counts)+'秒无信息服务器断连) Disconnect'+client.name);
                          {$ENDIF}
                          TIdPeerThread(Client.Thread).Connection.Disconnect;
                          End
                          except
                            begin
                            {$IFDEF Test_Client_keep}
                              writelog('(断开连接发生错误)DIS ERROR');
                            {$ENDIF}
                            end;                    end;
                      end;
                      {$IFDEF Test_Client_keep}
                          writelog('采集器名字'+client.name+'超时>30');
                      {$ENDIF}
                     // Clients.Delete(index);
                      client.delete:=true;
                     //  FreeAndNil(client);
                      end;
                    end;
            end
            else
            begin
                  Clients.Delete(index);
                  FreeAndNil(client);
            end;
    except
    begin
    clients.Delete(index);
    {$IFDEF Test_Client_keep}
    writelog('client_keepTimer处理过程发生错误Clients.items[index] error');
    {$ENDIF}
    end;
    end;
    end;
    End; 
      

  5.   

    我觉得用socket api写网络通信程序比较好,比indy更好!提议而已哈!我是菜菜!
      

  6.   

    用socket api写确实不错,我不管用TCP还是UDP我都用socket api来做的.不管是长连接还是短连接都没有任何问题.
      

  7.   

    就是没有跟踪测试的环境
    两个问题可能都在client_keepTimer
    一个问题出在Clients这个东东上
    第二个可能发生在
     TIdPeerThread(Client.Thread).Connection.Disconnect;
    是不是Thread也就是Athread已经结束,我还要去通过上面的方式去强行断开
    这样是不是就容易出现第二个错误呢。