-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f0a5fc4
commit c510f61
Showing
3 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
name = "chat_app" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
tokio = { version = "1", features = ["full"] } | ||
tokio-tungstenite = "0.15" | ||
tungstenite = "0.16" | ||
futures-util = "0.3" | ||
url = "2.2" | ||
warp = "0.3" | ||
|
||
[[bin]] | ||
name = "server" | ||
path = "src/server.rs" | ||
|
||
[[bin]] | ||
name = "client" | ||
path = "src/client.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Chat App</title> | ||
<style> | ||
body { | ||
font-family: Arial, sans-serif; | ||
margin: 0; | ||
padding: 0; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
background-color: #f4f4f4; | ||
} | ||
#chatContainer { | ||
width: 100%; | ||
max-width: 600px; | ||
height: 80%; | ||
display: flex; | ||
flex-direction: column; | ||
border: 1px solid #ccc; | ||
border-radius: 10px; | ||
overflow: hidden; | ||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | ||
background-color: #fff; | ||
} | ||
#chat { | ||
flex: 1; | ||
padding: 10px; | ||
overflow-y: auto; | ||
background-color: #f9f9f9; | ||
} | ||
#messageInput { | ||
display: flex; | ||
padding: 10px; | ||
background-color: #fff; | ||
border-top: 1px solid #ccc; | ||
} | ||
#messageInput input, #messageInput button { | ||
padding: 10px; | ||
border: 1px solid #ccc; | ||
border-radius: 5px; | ||
} | ||
#messageInput input { | ||
flex: 1; | ||
margin-right: 10px; | ||
} | ||
#messageInput button { | ||
background-color: #4CAF50; | ||
color: white; | ||
cursor: pointer; | ||
border-left: none; | ||
} | ||
.message { | ||
padding: 10px; | ||
margin: 10px 0; | ||
border-radius: 10px; | ||
background-color: #e1f5fe; | ||
word-wrap: break-word; | ||
} | ||
.message span { | ||
font-weight: bold; | ||
color: #00796b; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="chatContainer"> | ||
<div id="chat"></div> | ||
<div id="messageInput"> | ||
<input type="text" id="username" placeholder="Enter your name" autocomplete="off"> | ||
<input type="text" id="message" placeholder="Type your message here..." autocomplete="off"> | ||
<button onclick="sendMessage()">Send</button> | ||
</div> | ||
</div> | ||
|
||
<script> | ||
let ws = new WebSocket("ws://127.0.0.1:8080/ws"); | ||
|
||
ws.onmessage = function(event) { | ||
let chat = document.getElementById("chat"); | ||
let message = document.createElement("div"); | ||
message.className = "message"; | ||
message.textContent = event.data; | ||
chat.appendChild(message); | ||
chat.scrollTop = chat.scrollHeight; | ||
}; | ||
|
||
function sendMessage() { | ||
let usernameInput = document.getElementById("username"); | ||
let messageInput = document.getElementById("message"); | ||
if (usernameInput.value && messageInput.value) { | ||
let message = usernameInput.value + ": " + messageInput.value; | ||
ws.send(message); | ||
messageInput.value = ''; | ||
} else { | ||
alert("Please enter both your name and a message."); | ||
} | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use tokio::net::TcpListener; | ||
use tokio_tungstenite::accept_async; | ||
use tokio_tungstenite::tungstenite::protocol::Message; | ||
use futures_util::{StreamExt, SinkExt}; | ||
use std::sync::{Arc, Mutex}; | ||
use tokio::sync::broadcast; | ||
use warp::Filter; | ||
use warp::fs::File; | ||
use std::convert::Infallible; | ||
#[tokio::main] | ||
async fn main() { | ||
// Set up the broadcast channel | ||
let (tx, _rx) = broadcast::channel(100); | ||
let tx = Arc::new(Mutex::new(tx)); | ||
// WebSocket handler | ||
let tx_ws = tx.clone(); | ||
let ws_route = warp::path("ws") | ||
.and(warp::ws()) | ||
.map(move |ws: warp::ws::Ws| { | ||
let tx = tx_ws.clone(); | ||
ws.on_upgrade(move |websocket| handle_connection(websocket, tx)) | ||
}); | ||
// Static file handler | ||
let static_route = warp::path::end() | ||
.and(warp::fs::file("static/index.html")); | ||
// Combine routes | ||
let routes = ws_route.or(static_route); | ||
println!("Server listening on 127.0.0.1:8080"); | ||
// Start the server | ||
warp::serve(routes) | ||
.run(([127, 0, 0, 1], 8080)) | ||
.await; | ||
} | ||
async fn handle_connection(ws: warp::ws::WebSocket, tx: Arc<Mutex<broadcast::Sender<String>>>) { | ||
let (mut ws_sender, mut ws_receiver) = ws.split(); | ||
// Subscribe to the broadcast channel | ||
let mut rx = tx.lock().unwrap().subscribe(); | ||
// Task to send broadcast messages to the client | ||
tokio::spawn(async move { | ||
while let Ok(msg) = rx.recv().await { | ||
if ws_sender.send(warp::ws::Message::text(msg)).await.is_err() { | ||
break; | ||
} | ||
} | ||
}); | ||
// Process incoming messages | ||
while let Some(result) = ws_receiver.next().await { | ||
match result { | ||
Ok(message) => { | ||
if let Ok(text) = message.to_str() { | ||
println!("Received message: {}", text); | ||
tx.lock().unwrap().send(text.to_string()).expect("Failed to broadcast message"); | ||
} | ||
}, | ||
Err(e) => { | ||
eprintln!("Error receiving message: {}", e); | ||
break; | ||
} | ||
} | ||
} | ||
} |