最近学习局域网聊天程序,发现在线人较多(5-6个同时在线)的时候很容易出现程序死掉。
程序结构是这样的:
用一个TIdUDPServer监听端口,用一个timer每个几秒种广播一次在线,TIdUDPServer既做客户端又做服务端,发现很容易死掉,比如同时在线几个人,我在某台机器上发,另外的机上很容易死掉,这里的死掉是鼠标点击无响应,只能通过任务管理器关闭进程,对网络只知皮毛,恳请大家多多指教

解决方案 »

  1.   

    程序代码和这个类似unit frm_Chart;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      StdCtrls, ExtCtrls, ScktComp, IdUDPBase, IdUDPClient,IdSocketHandle,
      IdUDPServer, XPMan, ComCtrls;Const
       CPort=5966;type
      TFrmChar = class(TForm)
        EdSpeek: TEdit;
        Label1: TLabel;
        CBxOnlineMan: TComboBox;
        Label2: TLabel;
        GBxList: TGroupBox;
        MmText: TMemo;
        GBxBody: TGroupBox;
        LBxLineMan: TListBox;
        BtnSend: TButton;
        UServer: TIdUDPServer;
        CheckBody: TTimer;
        procedure CheckBodyTimer(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure UServerUDPRead(Sender: TObject; AData: TStream;
          ABinding: TIdSocketHandle);
        procedure FormDestroy(Sender: TObject);
        procedure FormShow(Sender: TObject);
        procedure BtnSendClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure CBxOnlineManDropDown(Sender: TObject);
        procedure FormKeyUp(Sender: TObject; var Key: Word;
          Shift: TShiftState);
        procedure LBxLineManDblClick(Sender: TObject);
      private
        ExitFlag:boolean;
        OnlineList:TStrings;
        procedure ASendMessage(AHost:string;AMessage:string);
        Procedure onlineMes(const Amessage:string);
        { Private declarations }
      public
        { Public declarations }
      end;var
      FrmChar: TFrmChar;implementation{$R *.dfm}
    Procedure TFrmChar.onlineMes(const Amessage:string);
    begin
      try
        if not Userver.BroadcastEnabled then
          Userver.BroadcastEnabled:=True;
        UServer.Broadcast(AMessage,CPort);
      except
        Exit;
      end;
    end;procedure TFrmChar.CheckBodyTimer(Sender: TObject);
    begin
      LbxLineMan.Clear;
      if ExitFlag then
      begin
        Self.Close;
        exit;
      end;
      OnlineMes('*Is On line*;'+UServer.LocalName);
    end;procedure TFrmChar.FormCreate(Sender: TObject);
    begin
      try
        UServer.DefaultPort:=CPort;
        UServer.Active:=true;
      except
        Application.MessageBox('由于某种原因导致网络启动失败!','错误',MB_OK+MB_ICONERROR);
      end;
      OnlineList:=TStringList.create;
    end;procedure TFrmChar.UServerUDPRead(Sender: TObject; AData: TStream;
      ABinding: TIdSocketHandle);
    var
      RemoString,RecString,Cmd:String;
      SBuffer:Array [0..1024] of char;
    begin
      remostring:='';
      RecString:='';
      SBuffer:='';
      AData.Read(SBuffer,Adata.Size);
      RecString:=trim(SBuffer);
      if Pos('*Is On line*',RecString) > 0 then
      begin
        RemoString:=copy(RecString,Pos(';',RecString)+1,Length(RecString));
        ASendmessage(Remostring,'*OnLine*;'+Userver.LocalName);
      end;  if Pos('*FirstLogin*',RecString) > 0 then
      begin
        RemoString:=copy(RecString,Pos(';',RecString)+1,Length(RecString));
        Mmtext.Lines.Add(RemoString+'  上线了!');
        Application.Restore;
        Application.BringToFront;
       end;  if Pos('*OnLine*',RecString) > 0 then
      begin
        remostring:=copy(RecString,Pos('*;',RecString)+2,Length(RecString));
        if pos(remostring,LbxLineman.Items.Text)> 0 then
        exit;
        LbxLineMan.Items.Add(RemoString);
      end;  if pos('*Speek*',Recstring) > 0 then
      begin
        Recstring:=copy(RecString,Pos('*;',RecString)+2,Length(RecString));  //dele speek
        remoString:=copy(Recstring,0,Pos('*;',RecString)-1);                //get remodeserver
        Recstring:=copy(RecString,Pos('*;',RecString)+2,Length(RecString));
        if Remostring <> UServer.LocalName then
        begin
        if pos('!*Command*!',Recstring)>0 then
        begin
          cmd:=Copy(RecString,Pos('!*Command*! ',RecString)+11,Length(RecString));
          if pos('Exit',Cmd)>0 then
            begin
              ExitFlag:=true;
              CHeckBody.Enabled:=false;
              CheckBody.Interval:=500;
              CheckBody.Enabled:=true;
              Exit;
            end;
        end;
          Mmtext.Lines.Add(remostring+' 对你说:['+' 时间:'+DatetimeTostr(Now)+']');
          Mmtext.Lines.Add(Recstring);
          Application.Restore;
          Application.BringToFront;
        end;
      end;  if pos('*Quit*',Recstring) > 0 then
      begin
        remostring:=copy(RecString,Pos('*;',RecString)+2,Length(RecString));
        Mmtext.Lines.Add(remoString+' 离开了!');
        LbxLineMan.Items.Delete(LbxLineMan.Items.IndexOf(remostring));
      end;end;procedure TFrmChar.FormDestroy(Sender: TObject);
    begin
      OnlineList.Free;
    end;procedure TFrmChar.FormShow(Sender: TObject);
    begin
      LbxLineMan.Clear;
      OnlineMes('*FirstLogin*;'+Userver.LocalName);
      onlineMes('*Is On line*;'+UServer.LocalName);
    end;procedure TFrmChar.ASendMessage(AHost:string;AMessage:string);
    begin
      try
        Userver.Send(AHost,Cport,AMessage);
      except
        exit;
      end;
    end;procedure TFrmChar.BtnSendClick(Sender: TObject);
    var
      AMessage:string;
    begin
      if CBXOnlineMan.Text = '' then
      begin
        Showmessage('请选择接收者!');
        exit;
      end;
      if EDSpeek.Text = '' then
      begin
        Showmessage('不能发送空信息!');
        exit;
      end;
      AMessage:='*Speek*;'+UServer.LocalName+'*;'+EDSpeek.Text;
      if CbxOnlineMan.Text = '所有人' then
        onlineMes(AMessage)
        else
          ASendMessage(CBXOnlineMan.Text,AMessage);
        Mmtext.Lines.Add('你对 '+CBXOnlineMan.Text+' 说:['+' 时间:'+datetimetostr(now)+']');
        Mmtext.Lines.Add(EDSpeek.Text);
      EDSpeek.Clear;
      Application.Minimize;
    end;procedure TFrmChar.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      onlineMes('*Quit*;'+UServer.LocalName);
      UServer.Active:=false;
    end;procedure TFrmChar.CBxOnlineManDropDown(Sender: TObject);
    begin
      CBxOnlineMan.Items.Assign(LbxLineMan.Items);
      CbxOnlineMan.Items.Add('所有人');
    end;procedure TFrmChar.FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if (key=13) and ((GetKeyState(VK_CONTROL) and ($F0000000))<>0)then
      begin
        BtnSendClick(nil);
      end;
    end;procedure TFrmChar.LBxLineManDblClick(Sender: TObject);
    begin
      if LbxLineMan.Count > 0 then
      begin
        CbxOnlineMan.Clear;
        CbxOnlineMan.Items.Assign(LbxLineMan.Items);
        CbxOnlineMan.ItemIndex:=LbxLineMan.ItemIndex;
      end;
    end;end.