我在用idTCPserver和idTCPClient相互传递字符串,客户端运行中接受完数据后就没有反应了,F8跟踪后发现
到从buffer中读完数据后就停止在 msg := idtcpclient1.ReadLn();
可以接受直到服务端有writln数据,就是客户端不能操作,直到把timer.active = false。
是不是在timer中idtcpclient1.ReadLn()取完数据后一直在那里等待服务端的消息?这样肯定不行我还有在客户端输数据,是啥原因?
这个例子是Demo中搬过来的,运行Demo也是这样。
怎么办????我可是第一次做网络开发,这应该是最基本的吧!!客户端中timer:
procedure Tc_main.Timer1Timer(Sender: TObject);
var
  msg : String;
begin
  try
    if not idTCPClient1.Connected then
       exit;
    msg := idtcpclient1.ReadLn();
    ListBox1.Items.Add(msg) ;
  except
    Button2.Click
  end;  
end;

解决方案 »

  1.   

    服务端代码
    unit u_main;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdBaseComponent, IdComponent, IdTCPServer, StdCtrls, Spin,
      ComCtrls, ToolWin, ImgList, ExtCtrls, IdThreadMgr, IdThreadMgrDefault;
    type
      TSimpleClient = class(TObject)
        DNS,
        Name        : String;
        ListLink    : Integer;
        Thread      : Pointer;
      end;  Tmain = class(TForm)
        seBinding: TSpinEdit;
        Label4: TLabel;
        Label3: TLabel;
        lblDNS: TLabel;
        idtcpServer: TIdTCPServer;
        Panel2: TPanel;
        lbClients: TListBox;
        memEMotes: TMemo;
        memEntry: TMemo;
        ListBox1: TListBox;
        IdThreadMgrDefault1: TIdThreadMgrDefault;
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        procedure idtcpServerConnect(AThread: TIdPeerThread);
        procedure FormCreate(Sender: TObject);
        procedure idtcpServerDisconnect(AThread: TIdPeerThread);
        procedure idtcpServerExecute(AThread: TIdPeerThread);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        Clients  : TList;
        procedure UpdateClientList;
         procedure BroadcastMessage( WhoFrom, TheMessage : String );
      end;var
      main: Tmain;implementation{$R *.dfm}procedure Tmain.idtcpServerConnect(AThread: TIdPeerThread);
    var
      Client : TSimpleClient; //TSimpleClient是一个自定义类,用来管理客户连接
    begin
    { 发送连接消息给客户端 }
      AThread.Connection.WriteLn('ISD Connection Established...');
      AThread.Connection.WriteLn('Please send valid login sequence...');
      AThread.Connection.WriteLn('Your Name:');
    { Create a client object }
      Client := TSimpleClient.Create;
    { Assign its default values 标记链接}
      Client.DNS  := AThread.Connection.LocalName;
      Client.Name := 'Logging In';  Client.ListLink := lbClients.Items.Count;{ Assign the thread to it for ease in finding }
    //标记线程
      Client.Thread := AThread;  { Add to our clients list box }
      //在list列表中显示
      lbClients.Items.Add(Client.Name);
    { Assign it to the thread so we can identify it later }
      AThread.Data := Client;
    { Add it to the clients list }
      Clients.Add(Client); //把每个连接的客户加入客户管理集
    end;procedure Tmain.FormCreate(Sender: TObject);
    begin
       Clients := TList.Create;
    end;procedure Tmain.idtcpServerDisconnect(AThread: TIdPeerThread);
    var
      Client : TSimpleClient;
    begin
    { Retrieve Client Record from Data pointer }
      Client := Pointer(AThread.Data);
    { Remove Client from the Clients TList }
      Clients.Delete(Client.ListLink);
    { Remove Client from the Clients List Box }
      lbClients.Items.Delete(lbClients.Items.IndexOf(Client.Name));
      BroadcastMessage('System', Client.Name + ' has left the chat.');
    { Free the Client object }
      Client.Free;
      AThread.Data := nil;
    end;procedure Tmain.BroadcastMessage( WhoFrom, TheMessage : String ); //广播消息
    var
      Count: Integer;
      List : TList;
      EMote,
      Msg  : String;
    begin  Msg := Trim(TheMessage);
      EMote := Trim(memEMotes.Lines.Values[Msg]);
      if WhoFrom <> 'System' then
        Msg := WhoFrom + ': ' + Msg;
      if EMote <> '' then
        Msg := Format(Trim(EMote), [WhoFrom]);
      List := idtcpServer.Threads.LockList; //取得所有客户列表
      try
        for Count := 0 to List.Count -1 do //遍历所有客户
        try
          TIdPeerThread(List.Items[Count]).Connection.WriteLn(Msg); //向客户写字符串
        except
          TIdPeerThread(List.Items[Count]).Stop;
        end;
      finally
        idtcpServer.Threads.UnlockList;
      end;end;procedure Tmain.idtcpServerExecute(AThread: TIdPeerThread);
    var
      Client : TSimpleClient;
      Com,     // System command
      Msg    : String;
    begin
      Msg    := AThread.Connection.ReadLn(); //读取客户传来的字符串
      ListBox1.Items.Add(Msg);
    end;
    procedure Tmain.UpdateClientList;
    var
      Count : Integer;
    begin
    { Loop through all the clients connected to the system and set their names }
      for Count := 0 to lbClients.Items.Count -1 do
        if Count < Clients.Count then
          lbClients.Items.Strings[Count] := TSimpleClient(Clients.Items[Count]).Name;
    end;
    procedure Tmain.Button1Click(Sender: TObject);
    begin
      try
        idtcpServer.Active :=true;
      except  end;
    end;procedure Tmain.Button2Click(Sender: TObject);
    begin
     try
        idtcpServer.Active :=false;
      except  end;
    end;end.
      

  2.   

    客户端代码
    unit C_main_u;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      ExtCtrls, StdCtrls, Spin;type
      Tc_main = class(TForm)
        IdTCPClient1: TIdTCPClient;
        Timer1: TTimer;
        Label1: TLabel;
        edt_serverhost: TEdit;
        btn_connect: TButton;
        btn_disconnect: TButton;
        Label2: TLabel;
        SpinEdit1: TSpinEdit;
        ListBox1: TListBox;
        ListBox2: TListBox;
        Edit1: TEdit;
        Label3: TLabel;
        Button1: TButton;
        Button2: TButton;
        procedure IdTCPClient1Connected(Sender: TObject);
        procedure btn_connectClick(Sender: TObject);
        procedure btn_disconnectClick(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure Edit1KeyPress(Sender: TObject; var Key: Char);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      c_main: Tc_main;implementation{$R *.dfm}procedure Tc_main.IdTCPClient1Connected(Sender: TObject);
    begin
        //WriteLn( 'conn:' + IdTCPClient1.BoundIP );
        //WriteLn( 'conned ok!');
    end;procedure Tc_main.btn_connectClick(Sender: TObject);
    begin
      if edt_serverhost.Text <> '' then
      begin
        IdTCPClient1.Host := edt_serverhost.Text;
        IdTCPClient1.Port := SpinEdit1.Value ;
        IdTCPClient1.Connect;
      end;
    end;procedure Tc_main.btn_disconnectClick(Sender: TObject);
    begin
      IdTCPClient1.Disconnect ;
    end;procedure Tc_main.Timer1Timer(Sender: TObject);
    var
      msg : String;
    begin
    try
      if not idTCPClient1.Connected then
         exit;
     
      msg := idtcpclient1.ReadLn();
      ListBox1.Items.Add('00' + msg) ;except
      Button2.Click
    end;end;
    procedure Tc_main.Edit1KeyPress(Sender: TObject; var Key: Char);
    begin
      if key = #13 then
      begin
        idtcpclient1.WriteLn(edit1.Text);
      end ;
    end;procedure Tc_main.Button2Click(Sender: TObject);
    begin
       timer1.Enabled := not timer1.Enabled ;end;end.
      

  3.   

    你没设置超时的原因。这个时间可以自己来掌握
    tcpclta.ReadLn(#$A, 30);
      

  4.   

    procedure Tc_main.Timer1Timer(Sender: TObject); 
    var 
      msg : String; 
    begin 
      try 
        if not idTCPClient1.Connected then 
          exit; 
        msg := idtcpclient1.ReadLn(#$A, 30); //带参数也不行
        ListBox1.Items.Add(msg) ; 
      except 
        Button2.Click 
      end;  
    end;带参数后也不行,不应该是参数的问题吧!
    idtcpclient是不是阻塞的方式,是不是要用线程解决?
    可惜我不会用线程!谁例子,
    谢谢!!
      

  5.   

    加idantifreeze解除“冻结”后效果也不好,看来只能用线程了。
    我可是第一次用线程,谁有比较好的例子,比较简单线程引用的例子
      

  6.   

    如果是阻塞模式的话,Readln就会一直等待,直到收到了数据。
    下面只是大概写了下,具体的还要你自己来完成TTcpRecvThread = Class(TThread)
    private
      fMsg: string;
      fList: TListBox;
      fTcp: TTcpClient;
      procedure Execute; override;
      procedure addMsg;
    public 
      constructor Create(CreateSuspended: boolean; aIp, aPort: string; aList: TListBox); overload;
    end;constructor TTcpRecvThread.Create(CreateSuspended: boolean; aIp, aPort: string; aList: TListBox);
    begin
      inherited create(CreateSuspended);
      //初始化fTcp  , fList
      fList := aList;
      ......
    end;procedure TTcpRecvThread.addMsg;
    begin
      if fList <> nil then
        fList.Items.Add(fmsg); 
    end;//如果用的复杂点 这里就用临界区来保护全局内存 cs: TCriticalSection; 
    procedure TTcpRecvThread.Execute;
    begin
      while not terminated do
      begin
        fMsg := fTcp.ReadLn;
         Synchronize(addMsg);
        sleep(50);
      end;
    end;