我用Delphi做了一个聊天程序,请问怎样在客户端动态显示其它机器的登录情况? 100分送上 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用indy的话,当client 连接上server 的时候在server的connected事件把client的名字添加到memo就是了。应该可以的。 聊天室主要采用UDP协议制作,当有客户连接服务器时,服务器应通知所有客户端 你的聊天程序是局域网的还是inter网的? 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. 聊天室主要采用UDP协议制作,当有客户连接服务器时,服务器应通知所有客户端 用delphi 可以实现web server 吗? 多年来,编程生涯有感 dbgrid如何做到自适应列宽? 200分送你。关于统计。 招Delphi程序員 CommandText Cann't Changed? 各位兄弟问一下,delphi客户端怎么调用dcom中的一个方法 在线等待,进度条的问题! 怎么使用EXE文件的参数 请问如何在XML节点中保存UniCode字符? 请问如何在C/S端程序的客户端连接到不是局域网内的Sql server服务器 表操作问题??
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.