import asyncio import websockets import json # Dictionary to hold chatrooms and their connected clients chatrooms = {} async def handle_connection(websocket, path): print('Client connected') async for message in websocket: print(f'Received message: {message}') try: message_data = json.loads(message) action = message_data.get('action') chat_room_id = message_data.get('chat_room_id') text_message = message_data.get('message') if action == 'sendMessage': # Add the websocket to the chatroom if not already present if chat_room_id not in chatrooms: chatrooms[chat_room_id] = [] if websocket not in chatrooms[chat_room_id]: chatrooms[chat_room_id].append(websocket) # Broadcast the message to all clients in the chatroom except the sender for s in chatrooms[chat_room_id]: # if s is not websocket: try: await s.send(json.dumps({ 'chat_room_id': chat_room_id, 'message': text_message, })) except: # Remove the socket if sending fails chatrooms[chat_room_id].remove(s) except Exception as e: await websocket.send(json.dumps({'error': f'Error processing message: {e}'})) print('Client disconnected') # Clean up chatrooms for room, sockets in list(chatrooms.items()): if websocket in sockets: sockets.remove(websocket) # Remove the chatroom if no more clients are connected if not sockets: del chatrooms[room] async def run_server(): server = await websockets.serve(handle_connection, 'localhost', 4040) print('WebSocket server is running on ws://localhost:4040') await server.wait_closed() if __name__ == '__main__': asyncio.run(run_server())
import asyncio
import websockets
import json
# Dictionary to hold chatrooms and their connected clients
chatrooms = {}
async def handle_connection(websocket, path):
print('Client connected')
async for message in websocket:
print(f'Received message: {message}')
try:
message_data = json.loads(message)
action = message_data.get('action')
chat_room_id = message_data.get('chat_room_id')
text_message = message_data.get('message')
if action == 'sendMessage':
# Add the websocket to the chatroom if not already present
if chat_room_id not in chatrooms:
chatrooms[chat_room_id] = []
if websocket not in chatrooms[chat_room_id]:
chatrooms[chat_room_id].append(websocket)
# Broadcast the message to all clients in the chatroom except the sender
for s in chatrooms[chat_room_id]:
# if s is not websocket:
try:
await s.send(json.dumps({
'chat_room_id': chat_room_id,
'message': text_message,
}))
except:
# Remove the socket if sending fails
chatrooms[chat_room_id].remove(s)
except Exception as e:
await websocket.send(json.dumps({'error': f'Error processing message: {e}'}))
print('Client disconnected')
# Clean up chatrooms
for room, sockets in list(chatrooms.items()):
if websocket in sockets:
sockets.remove(websocket)
# Remove the chatroom if no more clients are connected
if not sockets:
del chatrooms[room]
async def run_server():
server = await websockets.serve(handle_connection, 'localhost', 4040)
print('WebSocket server is running on ws://localhost:4040')
await server.wait_closed()
if __name__ == '__main__':
asyncio.run(run_server())
Python server
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:youtube/main.dart';
// For WebSocketChannel
class ChatScreen extends StatefulWidget {
final String selectedEmail;
const ChatScreen({
required this.selectedEmail,
super.key,
});
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State {
final TextEditingController _messageController = TextEditingController();
late final String chatRoomId;
final List messages = [];
@override
void initState() {
super.initState();
chatRoomId = getChatRoomId();
}
@override
void dispose() {
channel!.sink.close();
_messageController.dispose();
super.dispose();
}
String getChatRoomId() {
final sortedEmails = [widget.selectedEmail, myEmail]..sort();
return sortedEmails.join('_');
}
void _sendMessage() {
final message = _messageController.text;
final messageData = {
'action': 'sendMessage',
'chat_room_id': chatRoomId,
'message': message,
};
channel!.sink.add(jsonEncode(messageData));
_messageController.clear();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chat with ${widget.selectedEmail}'),
),
body: Column(
children: [
Expanded(
child: StreamBuilder(
stream: channel!.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (!snapshot.hasData) {
return const Center(child: Text('No messages yet.'));
}
// Decode and process the message data
final data = jsonDecode(snapshot.data.toString());
if (data['chat_room_id'] == chatRoomId) {
final message = data['message'];
// Update the messages list directly
messages.add(message);
}
return ListView.builder(
itemCount: messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(messages[index]),
);
},
);
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _messageController,
decoration: const InputDecoration(
labelText: 'Enter message',
),
),
),
IconButton(
icon: Icon(Icons.send),
onPressed: _sendMessage,
),
],
),
),
],
),
);
}
}
chat screen
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:youtube/chat.dart';
import 'main.dart';
class Home extends StatefulWidget {
const Home({super.key});
@override
State createState() => _HomeState();
}
class _HomeState extends State {
final TextStyle myStyle = const TextStyle(fontSize: 30, fontWeight: FontWeight.w600);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home', style: myStyle)),
body: ListView(
children: [
if(myEmail!='abc@gmail.com')
ListTile(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=>const ChatScreen(selectedEmail: 'abc@gmail.com',)));
},
leading: const Icon(Icons.supervised_user_circle),
title: Text('abc@gmail.com', style: myStyle),
),
if(myEmail!='def@gmail.com')
ListTile(
onTap: () =>Navigator.push(context, MaterialPageRoute(builder: (context)=>const ChatScreen (selectedEmail: 'def@gmail.com',))),
leading: const Icon(Icons.supervised_user_circle),
title: Text('def@gmail.com', style: myStyle),
),
ListTile(
onTap: () =>Navigator.push(context, MaterialPageRoute(builder: (context)=>const ChatScreen (selectedEmail: 'jawad@gmail.com',))),
leading: const Icon(Icons.supervised_user_circle),
title: Text('jawad@gmail.com', style: myStyle),
),
],
),
);
}
}
Home screen
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'login.dart';
String myEmail='';
WebSocketChannel ? channel;
void main() {
runApp(const MyApp());
channel = WebSocketChannel.connect(Uri.parse('ws://0.0.0.0:4040'));
//runServer();
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: false,
primarySwatch: Colors.purple
),
home: LoginScreen(),
);
}
}
Future runServer() async {
print(InternetAddress.anyIPv4);
final server = await HttpServer.bind(InternetAddress.anyIPv4, 4040);
print('WebSocket server is running on ws://localhost:4040');
// Map to hold chatrooms and their connected clients
final Map chatrooms = {};
server.transform(WebSocketTransformer()).listen((WebSocket socket) {
print('Client connected');
// Handle incoming messages
socket.listen((message) {
print('Received message: $message');
try {
final messageData = jsonDecode(message);
final action = messageData['action'];
final chatRoomId = messageData['chat_room_id'];
final textMessage = messageData['message'];
if (action == 'sendMessage') {
// Add the socket to the chatroom if not already present
if (!chatrooms.containsKey(chatRoomId)) {
chatrooms[chatRoomId] = [];
}
// Ensure the socket is not added multiple times
if (!chatrooms[chatRoomId]!.contains(socket)) {
chatrooms[chatRoomId]!.add(socket);
}
// Broadcast the message to all clients in the chatroom except the sender
for (final s in chatrooms[chatRoomId]!) {
// if (s != socket) {
s.add(jsonEncode({
'chat_room_id': chatRoomId,
'message': textMessage,
}));
//}
}
}
} catch (e) {
socket.add(jsonEncode({'error': 'Error processing message: $e'}));
}
}, onDone: () {
print('Client disconnected');
chatrooms.forEach((_, sockets) {
sockets.remove(socket);
// Remove the chatroom if no more clients are connected
if (sockets.isEmpty) {
chatrooms.remove(_);
}
});
});
});
}
main screen