Skip to content

Commit f1442d5

Browse files
committed
add: websocketserver, groups handling
1 parent 69dae2d commit f1442d5

16 files changed

+2515
-739
lines changed

samples/websocket_chat/README.md

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
# 💬 WebSocket Chat Demo
2+
3+
A beautiful, real-time chat application built with **DelphiMVCFramework** demonstrating WebSocket functionality with HTTP server integration.
4+
5+
## 🌟 Overview
6+
7+
This demo showcases how to create a complete chat application using:
8+
- **HTTP Server** (port 8080) - Serves the web client interface
9+
- **WebSocket Server** (port 9091) - Handles real-time chat communication
10+
11+
The application demonstrates the common pattern of running HTTP and WebSocket servers on different ports, which is typical in production environments.
12+
13+
## ✨ Features
14+
15+
### Server Features
16+
- ✅ Dual server architecture (HTTP + WebSocket)
17+
- ✅ Real-time message broadcasting to all connected users
18+
- ✅ User join/leave notifications
19+
- ✅ Online user counter
20+
- ✅ Custom username support
21+
- ✅ Server-side logging with timestamps
22+
- ✅ Clean separation of concerns
23+
24+
### Web Client Features
25+
- 🎨 Beautiful gradient UI design
26+
- 📱 Responsive layout
27+
- 👤 Random username generation
28+
- 💬 Real-time message display
29+
- 📊 Live user count
30+
- 🔔 Visual notifications for join/leave events
31+
- ⌨️ Enter key support for sending messages
32+
- 🎯 Message type distinction (own/other/server)
33+
- ⏰ Timestamp for each message
34+
- 🖱️ Smooth animations and transitions
35+
36+
## 🚀 How to Run
37+
38+
### Step 1: Compile the Server
39+
```bash
40+
cd c:\DEV\dmvcframework\samples\websocket_chat
41+
dcc32 WebSocketChatServer.dpr
42+
```
43+
44+
### Step 2: Run the Server
45+
```bash
46+
WebSocketChatServer.exe
47+
```
48+
49+
You should see:
50+
```
51+
=======================================================
52+
DMVCFramework WebSocket Chat Demo
53+
=======================================================
54+
55+
Starting HTTP server on port 8080...
56+
-> HTTP server running at http://localhost:8080/
57+
58+
Starting WebSocket server on port 9091...
59+
-> WebSocket server running at ws://localhost:9091/
60+
61+
=======================================================
62+
READY! Open your browser to:
63+
http://localhost:8080/
64+
=======================================================
65+
```
66+
67+
### Step 3: Open Multiple Browser Windows
68+
1. Open your browser to `http://localhost:8080/`
69+
2. Enter a username (or use the randomly generated one)
70+
3. Click "Join Chat"
71+
4. Open another browser window/tab to simulate multiple users
72+
5. Start chatting!
73+
74+
## 📁 Project Structure
75+
76+
```
77+
websocket_chat/
78+
├── WebSocketChatServer.dpr # Main program (HTTP + WebSocket servers)
79+
├── WebModuleU.pas/dfm # Web module for serving static files
80+
├── www/
81+
│ └── index.html # Beautiful web chat client
82+
└── README.md # This file
83+
```
84+
85+
## 💻 Code Highlights
86+
87+
### Server Architecture
88+
89+
The main program creates two servers:
90+
91+
```delphi
92+
// HTTP Server for web client
93+
LWebServer := TIdHTTPWebBrokerBridge.Create(nil);
94+
LWebServer.DefaultPort := 8080;
95+
LWebServer.Active := True;
96+
97+
// WebSocket Server for chat
98+
LWSServer := TMVCWebSocketServer.Create(9091);
99+
LWSServer.Active := True;
100+
```
101+
102+
### Event-Based Chat Implementation
103+
104+
The chat server uses anonymous methods for clean, inline event handling:
105+
106+
```delphi
107+
// Handle incoming messages - broadcast to all
108+
LWSServer.OnMessage := procedure(AClient: TWebSocketClient; const AMessage: string)
109+
var
110+
LChatMsg: string;
111+
begin
112+
LChatMsg := Format('[%s]: %s', [AClient.ClientId, AMessage]);
113+
AClient.Broadcast(LChatMsg); // Send to ALL clients including sender
114+
end;
115+
116+
// Handle client connection - notify all users
117+
LWSServer.OnClientConnect := procedure(AClient: TWebSocketClient)
118+
var
119+
LWelcomeMsg: string;
120+
begin
121+
LWelcomeMsg := Format('[SERVER]: %s joined the chat', [AClient.ClientId]);
122+
AClient.Broadcast(LWelcomeMsg);
123+
end;
124+
125+
// Handle disconnection - notify remaining users
126+
LWSServer.OnClientDisconnect := procedure(AClient: TWebSocketClient)
127+
var
128+
LGoodbyeMsg: string;
129+
begin
130+
LGoodbyeMsg := Format('[SERVER]: %s left the chat', [AClient.ClientId]);
131+
AClient.BroadcastToPeers(LGoodbyeMsg); // Send to all EXCEPT disconnecting client
132+
end;
133+
```
134+
135+
**Key Features:**
136+
- `AClient.Broadcast(msg)` - Send to all connected clients (including sender)
137+
- `AClient.BroadcastToPeers(msg)` - Send to all clients except sender
138+
- No need for custom server class - just use anonymous methods!
139+
140+
### Web Client Connection
141+
142+
The JavaScript client connects to the WebSocket server:
143+
144+
```javascript
145+
// Automatically uses current hostname with WebSocket port
146+
const wsUrl = `ws://${window.location.hostname}:9091/`;
147+
148+
// Connect with username in protocol header
149+
ws = new WebSocket(wsUrl, ['chat-' + username]);
150+
```
151+
152+
### Message Broadcasting Methods
153+
154+
Two convenient methods available on every `TWebSocketClient`:
155+
156+
```delphi
157+
// Broadcast to everyone (including sender)
158+
AClient.Broadcast('Message to all');
159+
160+
// Broadcast only to other clients (excluding sender)
161+
AClient.BroadcastToPeers('Message to others only');
162+
```
163+
164+
These methods are internally implemented as wrappers around the server's `BroadcastText` method, providing a more intuitive OOP API.
165+
166+
## 🎯 Message Format
167+
168+
The server uses a simple text-based message format:
169+
170+
- **Chat messages**: `[username]: message content`
171+
- **Join notification**: `[SERVER]: username joined the chat (N users online)`
172+
- **Leave notification**: `[SERVER]: username left the chat (N users online)`
173+
174+
The web client parses these messages and applies appropriate styling.
175+
176+
## 🏗️ How It Works
177+
178+
### 1. Server Startup
179+
1. HTTP server starts on port 8080
180+
2. WebSocket server starts on port 9091
181+
3. Both servers run in parallel
182+
183+
### 2. Client Connection
184+
1. Browser loads HTML from HTTP server (port 8080)
185+
2. JavaScript connects to WebSocket server (port 9091)
186+
3. Username sent via `Sec-WebSocket-Protocol` header
187+
188+
### 3. Message Flow
189+
```
190+
User A sends message
191+
192+
WebSocket Server receives
193+
194+
Server broadcasts to ALL clients
195+
196+
All users see message in real-time
197+
```
198+
199+
### 4. Join/Leave Events
200+
```
201+
New user connects
202+
203+
DoClientConnect called
204+
205+
Server broadcasts: "X joined the chat (N users online)"
206+
207+
All users see notification
208+
```
209+
210+
## 🔧 Customization Ideas
211+
212+
### Server-Side
213+
- Add private messaging between users
214+
- Implement chat rooms/channels
215+
- Add message persistence (database)
216+
- Implement user authentication
217+
- Add rate limiting per user
218+
- Implement admin commands
219+
- Add message filtering/moderation
220+
221+
### Client-Side
222+
- Add emoji picker
223+
- Implement typing indicators
224+
- Add message reactions
225+
- Show user list panel
226+
- Add dark/light theme toggle
227+
- Implement message search
228+
- Add file/image sharing
229+
- Show notification sounds
230+
- Add message timestamps
231+
- Implement user avatars
232+
233+
### Advanced Features
234+
- Add SSL/TLS support (wss://)
235+
- Implement reconnection logic
236+
- Add message delivery confirmation
237+
- Implement read receipts
238+
- Add push notifications
239+
- Implement user status (online/away/busy)
240+
241+
## 🐛 Troubleshooting
242+
243+
### Port Already in Use
244+
If you see errors about ports being in use:
245+
```bash
246+
# Check what's using the ports
247+
netstat -ano | findstr :8080
248+
netstat -ano | findstr :9091
249+
250+
# Kill the process or change ports in code
251+
```
252+
253+
### WebSocket Connection Failed
254+
1. Make sure the server is running
255+
2. Check browser console for errors
256+
3. Verify firewall isn't blocking ports
257+
4. Try accessing from `localhost` instead of `127.0.0.1`
258+
259+
### Can't See Other Users' Messages
260+
1. Make sure you're connected (status shows "Connected as [username]")
261+
2. Open browser developer console to check for WebSocket errors
262+
3. Verify server console shows both users connected
263+
264+
### Messages Not Broadcasting
265+
Check server console for errors. Each message should show:
266+
```
267+
[HH:MM:SS] <username> message content
268+
```
269+
270+
## 📚 What You'll Learn
271+
272+
- ✅ Running HTTP and WebSocket servers together
273+
- ✅ Serving static files via DMVCFramework
274+
- ✅ WebSocket connection management
275+
- ✅ Broadcasting messages to multiple clients
276+
- ✅ Handling client connect/disconnect events
277+
- ✅ Per-client state management
278+
- ✅ Building responsive web chat interfaces
279+
- ✅ JavaScript WebSocket API usage
280+
- ✅ Real-time message parsing and formatting
281+
- ✅ Modern CSS styling and animations
282+
283+
## 🎓 Educational Value
284+
285+
This demo is perfect for learning:
286+
287+
1. **WebSocket Basics** - See how real-time bidirectional communication works
288+
2. **Server Architecture** - Understand HTTP + WebSocket dual-server pattern
289+
3. **Event Handling** - Learn connection/disconnection event management
290+
4. **Message Broadcasting** - Understand how to send messages to multiple clients
291+
5. **Web UI Development** - Study modern responsive chat interface design
292+
6. **Protocol Design** - See simple message format and parsing
293+
294+
## 🌐 Production Considerations
295+
296+
When moving to production, consider:
297+
298+
- Use **SSL/TLS** (HTTPS + WSS)
299+
- Implement **authentication/authorization**
300+
- Add **rate limiting** to prevent spam
301+
- Implement **message validation** and sanitization
302+
- Add **database persistence** for message history
303+
- Implement **load balancing** for multiple server instances
304+
- Add **monitoring and logging**
305+
- Implement **graceful shutdown** handling
306+
- Add **health check endpoints**
307+
- Use **environment variables** for configuration
308+
309+
## 📖 Related Demos
310+
311+
- **websocket_primer** - Basic WebSocket server with periodic messages
312+
- **websocket_echo** - Simple echo server for testing
313+
314+
## 🤝 Contributing
315+
316+
Found a bug or have a feature request? Please open an issue on the DMVCFramework GitHub repository.
317+
318+
## 📄 License
319+
320+
This demo is part of the DelphiMVCFramework project.
321+
322+
---
323+
324+
**Enjoy real-time chatting with DMVCFramework! 💬**
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object WebModule1: TWebModule1
2+
OnCreate = WebModuleCreate
3+
OnDestroy = WebModuleDestroy
4+
Height = 230
5+
Width = 415
6+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
unit WebModuleU;
2+
3+
interface
4+
5+
uses
6+
System.SysUtils, System.Classes, Web.HTTPApp, MVCFramework;
7+
8+
type
9+
TWebModule1 = class(TWebModule)
10+
procedure WebModuleCreate(Sender: TObject);
11+
procedure WebModuleDestroy(Sender: TObject);
12+
private
13+
FMVC: TMVCEngine;
14+
public
15+
{ Public declarations }
16+
end;
17+
18+
var
19+
WebModuleClass: TComponentClass = TWebModule1;
20+
21+
implementation
22+
23+
{%CLASSGROUP 'System.Classes.TPersistent'}
24+
25+
uses
26+
MVCFramework.Commons,
27+
MVCFramework.Middleware.StaticFiles;
28+
29+
{$R *.dfm}
30+
31+
procedure TWebModule1.WebModuleCreate(Sender: TObject);
32+
begin
33+
FMVC := TMVCEngine.Create(Self);
34+
35+
// Serve static HTML chat client from www folder
36+
FMVC.AddMiddleware(TMVCStaticFilesMiddleware.Create(
37+
'/chat', { URL path }
38+
'.\www', { Physical path }
39+
'index.html' { Default document }
40+
));
41+
42+
// Redirect root to /chat
43+
FMVC.AddMiddleware(TMVCStaticFilesMiddleware.Create(
44+
'/',
45+
'.\www',
46+
'index.html'
47+
));
48+
end;
49+
50+
procedure TWebModule1.WebModuleDestroy(Sender: TObject);
51+
begin
52+
FMVC.Free;
53+
end;
54+
55+
end.

0 commit comments

Comments
 (0)