100分送上

解决方案 »

  1.   

    用indy的话,当client 连接上server 的时候在server的connected事件把client的名字添加到memo就是了。应该可以的。
      

  2.   

    聊天室主要采用UDP协议制作,当有客户连接服务器时,服务器应通知所有客户端
      

  3.   

    你的聊天程序是局域网的还是inter网的?
      

  4.   

    unit tx;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ExtCtrls, StdCtrls, WinSock, ScktComp, ComCtrls, OleCtrls, ShellApi,
      IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, IdSocketHandle,
      IdUDPClient, AppEvnts;const
     
    type
      Ttxx = class(TForm)
        BottomBevel: TBevel;
        EndBtn: TButton;
        ServerStatusLabel: TLabel;
        ClientCountLabel: TLabel;
        LabelA: TLabel;
        ShapeTitle: TShape;
        UDPServer: TIdUDPServer;
        MemoMsg: TMemo;
        UDPClient: TIdUDPClient;
        procedure FormCreate(Sender: TObject);
        procedure EndBtnClick(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure UDPServerUDPRead(Sender: TObject; AData: TStream;
          ABinding: TIdSocketHandle);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure ApplicationEventsMinimize(Sender: TObject);
        procedure FormActivate(Sender: TObject);
      private
        FClientDataList: TList;
        FClientID: Integer;
        FClientCount: Integer;
        FConnected: Boolean;
        FReceiveStream: TMemoryStream;
        FSendStream: TMemoryStream;
        ServerTrayIconData : TNotifyIconData;    procedure ServerTrayMessage(var Message: TMessage); message SERVER_TRAY_MESSAGE;
        procedure ClientConnect(ABinding: TIdSocketHandle);
        procedure ClientReceive(Data: TMemoryStream; ABinding: TIdSocketHandle);
        procedure ClientChat(Data: TMemoryStream; ABinding: TIdSocketHandle);
        procedure ClientLogout(Data: TMemoryStream; ABinding: TIdSocketHandle);
        procedure ShowClientCount;
      end;var
      txx: Ttxx;implementationuses
      
    {$R *.DFM}{============================================================}procedure Ttxx.FormCreate(Sender: TObject);
    begin
      FClientDataList := TList.Create;
      FClientID := 40000;
      FClientCount := 0;
      FConnected := False;
      FSendStream := TMemoryStream.Create;
      FReceiveStream := TMemoryStream.Create;
      FClientCount := 0;
      FConnected := True;
      ShowClientCount;
      UDPServer.Active := True;
      UDPClientServerPort := 8401;
      UDPServerPort := 8400;
      ServerStatusLabel.Caption := '服务器已经启动';
     end;{============================================================}procedure Ttxx.EndBtnClick(Sender: TObject);
    begin
      while FClientDataList.Count > 0 do FClientDataList.Remove(FClientDataList.Last);
      Close;
    end;{============================================================}procedure Ttxx.ClientChat(Data: TMemoryStream; ABinding: TIdSocketHandle);
    var
      AClientData: TxClientData;
      Vi, VCount: Integer;begin
      Data.Seek(SizeOf(AClientData), soFromCurrent);
      Data.Read(AClientData, SizeOf(AClientData));
      VCount := FClientCount - 1;
      for Vi := 0 to VCount do
      begin
        if AClientData.ClientID = PxClientData(FClientDataList.Items[Vi])^.ClientID then
        begin
          UDPClient.SendBuffer(PxClientData(FClientDataList.Items[Vi])^.IPAddress, UDPClientServerPort, Data.Memory^, Data.Size);
          Break;
        end;
      end;
    end;{============================================================}procedure Ttxx.ShowClientCount;
    begin
      ClientCountLabel.Caption :=  '在线用户:  ' + IntToStr(FClientCount);
    end;{============================================================}procedure Ttxx.FormDestroy(Sender: TObject);
    begin
      FReceiveStream.Free;
      FSendStream.Free;
      FClientDataList.Free;
    end;{============================================================}procedure Ttxx.UDPServerUDPRead(Sender: TObject; AData: TStream;
      ABinding: TIdSocketHandle);
    begin
      FReceiveStream.Clear;
      FReceiveStream.LoadFromStream(AData);
      FReceiveStream.Read(MessageID, SizeOf(MessageID));
      
      case MessageID of  //自定义MESSAGEID 检测客户端的请求
         xMIDConnect: begin
           ClientConnect(ABinding);
         end;
         xMIDClientData: begin
           ClientReceive(FReceiveStream, ABinding);
         end;
         xMIDChat: begin
           ClientChat(FReceiveStream, ABinding);
         end;
         xMIDClientLogout: begin
           ClientLogout(FReceiveStream, ABinding);
         end;
      end;
    end;{============================================================}procedure Ttxx.ClientConnect(ABinding: TIdSocketHandle);
    begin
      FSendStream.Clear;
      MessageID := xMIDConnectS;
      FSendStream.Write(MessageID, SizeOf(MessageID));
      UDPClient.SendBuffer(ABinding.PeerIP, UDPClientServerPort, FSendStream.Memory^, FSendStream.Size);
    end;{============================================================}procedure Ttxx.ClientReceive(Data: TMemoryStream;
      ABinding: TIdSocketHandle);
    var
      AClientData: PxClientData;
      Vi: Integer;
    begin
      New(AClientData);
      Data.Read(AClientData^, SizeOf(TxClientData));
      for Vi := 0 to FClientCount - 1 do
        if AClientData^.IPAddress = PxClientData(FClientDataList.Items[Vi])^.IPAddress then Exit;  Inc(FClientCount);
      AClientData^.ClientID := FClientID;
      Inc(FClientID);
      FClientDataList.Add(AClientData);  FSendStream.Clear;
      MessageID := xMIDClientData;
      FSendStream.Write(MessageID, SizeOf(MessageID));
      FSendStream.Write(AClientData^, SizeOf(TxClientData));
      for Vi := 0 to FClientCount - 2 do
        UDPClient.SendBuffer((PxClientData(FClientDataList.Items[Vi])^.IPAddress), UDPClientServerPort, FSendStream.Memory^, FSendStream.Size);  FSendStream.Clear;
      MessageID := xMIDClientDataS;
      FSendStream.Write(MessageID, SizeOf(MessageID));
      FSendStream.Write(FClientCount, SizeOf(FClientCount));
      for Vi := 0 to FClientCount - 1 do
        FSendStream.Write((FClientDataList.Items[Vi])^, SizeOf(TxClientData));
      UDPClient.SendBuffer(ABinding.PeerIP, UDPClientServerPort , FSendStream.Memory^, FSendStream.Size);  ShowClientCount;
      if MemoMsg.Lines.Count > 1024 then MemoMsg.Clear;
      MemoMsg.Lines.Add(' ' + AClientData.NickName + ' 来自于 ' + AClientData.IPAddress + ' 已经登录');
    end;{============================================================}procedure Ttxx.ClientLogout(Data: TMemoryStream; ABinding: TIdSocketHandle);
    var
      Vi, Vj, VCount: Integer;
      AClientData: TxClientData;
    begin
      Data.Read(AClientData, SizeOf(TxClientData));
      VCount := FClientCount - 1;
      for Vi := 0 to VCount do
      begin
        if AClientData.ClientID = PxClientData(FClientDataList.Items[Vi])^.ClientID then
        begin
          FSendStream.Clear;
          MessageID := xMIDClientLogout;
          FSendStream.Write(MessageID, SizeOf(MessageID));
          FSendStream.Write((FClientDataList.Items[Vi])^, SizeOf(TxClientData));
          for Vj := 0 to VCount do
          begin
            if Vj <> Vi then
              UDPClient.SendBuffer((PxClientData(FClientDataList.Items[Vj])^.IPAddress), UDPClientServerPort, FSendStream.Memory^, FSendStream.Size);
          end;
          FClientDataList.Remove(FClientDataList.Items[Vi]);
          Dec(FClientCount);
          ShowClientCount;
          if MemoMsg.Lines.Count > 1024 then MemoMsg.Clear;
          MemoMsg.Lines.Add(' ' + AClientData.NickName + ' 来自于 ' + AClientData.IPAddress + ' 已经断开');
          Break;
        end;
      end;
    end;{============================================================}procedure Ttxx.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      FSendStream.Clear;
      MessageID := xMIDServerExit;
      FSendStream.Write(MessageID, SizeOf(MessageID));
      UDPClient.SendBuffer(BROADCAST_ADDRESS, UDPClientServerPort, FSendStream.Memory^, FSendStream.Size);
      Shell_NotifyIcon(NIM_DELETE, @ServerTrayIconData);
    end;
    {============================================================}
    end.
      

  5.   

    聊天室主要采用UDP协议制作,当有客户连接服务器时,服务器应通知所有客户端