Last active
July 31, 2023 10:41
-
-
Save M0nteCarl0/55228c4bd18167019135c6f8540ce1ee to your computer and use it in GitHub Desktop.
Simple TCP chat client and server with private messages for connected users
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
package main | |
import ( | |
"bufio" | |
"fmt" | |
"net" | |
"os" | |
) | |
func readMessages(reader *bufio.Reader) { | |
for { | |
message, err := reader.ReadString('\n') | |
if err != nil { | |
fmt.Println("Error reading message:", err) | |
return | |
} | |
fmt.Println("Received message:", message) | |
} | |
} | |
func main() { | |
conn, err := net.Dial("tcp", "localhost:8080") | |
if err != nil { | |
fmt.Println("Error connecting to server:", err) | |
return | |
} | |
defer conn.Close() | |
reader := bufio.NewReader(conn) | |
go readMessages(reader) | |
fmt.Print("Enter your name: ") | |
name, _ := reader.ReadString('\n') | |
name = name | |
fmt.Printf("Welcome, %s! Start chatting:\n", name) | |
for { | |
message, _ := reader.ReadString('\n') | |
fmt.Print("Enter your message: ") | |
text, _ := reader.ReadString('\n') | |
text = text[:len(text)-1] | |
if text == "/exit" { | |
fmt.Println("Exiting the chat...") | |
return | |
} | |
if text == "/private" { | |
fmt.Print("Enter recipient's name: ") | |
recipient, _ := reader.ReadString('\n') | |
recipient = recipient[:len(recipient)-1] | |
fmt.Print("Enter your private message: ") | |
privateMessage, _ := reader.ReadString('\n') | |
privateMessage = privateMessage[:len(privateMessage)-1] | |
fmt.Fprintf(conn, fmt.Sprintf("/private %s %s\n", recipient, privateMessage)) | |
} else { | |
fmt.Fprintf(conn, text+"\n") | |
} | |
} |
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
package main | |
import ( | |
"bufio" | |
"fmt" | |
"net" | |
"strings" | |
) | |
type Client struct { | |
conn net.Conn | |
name string | |
writer *bufio.Writer | |
} | |
type Message struct { | |
sender string | |
content string | |
} | |
var ( | |
clients = make(map[string]Client) | |
broadcast = make(chan Message) | |
register = make(chan Client) | |
unregister = make(chan Client) | |
) | |
func main() { | |
listener, err := net.Listen("tcp", ":8080") | |
if err != nil { | |
fmt.Println("Error starting server:", err) | |
return | |
} | |
defer listener.Close() | |
fmt.Println("Server is running. Waiting for connections...") | |
go handleMessages() | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
fmt.Println("Error accepting connection:", err) | |
return | |
} | |
go handleClient(conn) | |
} | |
} | |
func handleClient(conn net.Conn) { | |
writer := bufio.NewWriter(conn) | |
fmt.Fprintf(writer, "Enter your name: ") | |
writer.Flush() | |
reader := bufio.NewReader(conn) | |
name, _ := reader.ReadString('\n') | |
name = strings.TrimRight(name, "\r\n") | |
client := Client{ | |
conn: conn, | |
name: name, | |
writer: writer, | |
} | |
register <- client | |
fmt.Printf("%s joined the chat\n", client.name) | |
for { | |
message, err := reader.ReadString('\n') | |
if err != nil { | |
fmt.Printf("%s left the chat\n", client.name) | |
unregister <- client | |
return | |
} | |
message = strings.TrimRight(message, "\r\n") | |
if strings.HasPrefix(message, "/private") { | |
parts := strings.SplitN(message, " ", 3) | |
if len(parts) >= 3 { | |
recipient := parts[1] | |
content := parts[2] | |
privateMessage := Message{sender: client.name, content: content} | |
sendPrivateMessage(recipient, privateMessage) | |
} | |
} else { | |
broadcast <- Message{sender: client.name, content: message} | |
} | |
} | |
} | |
func handleMessages() { | |
for { | |
select { | |
case client := <-register: | |
clients[client.name] = client | |
sendSystemMessage(fmt.Sprintf("%s joined the chat", client.name)) | |
case client := <-unregister: | |
delete(clients, client.name) | |
sendSystemMessage(fmt.Sprintf("%s left the chat", client.name)) | |
case message := <-broadcast: | |
sendBroadcastMessage(message) | |
} | |
} | |
} | |
func sendSystemMessage(message string) { | |
for _, client := range clients { | |
client.writer.WriteString("[System]: " + message + "\n") | |
client.writer.Flush() | |
} | |
} | |
func sendBroadcastMessage(message Message) { | |
for _, client := range clients { | |
if client.name != message.sender { | |
client.writer.WriteString(fmt.Sprintf("[%s]: %s\n", message.sender, message.content)) | |
client.writer.Flush() | |
} | |
} | |
} | |
func sendPrivateMessage(recipient string, message Message) { | |
client, ok := clients[recipient] | |
if ok { | |
client.writer.WriteString(fmt.Sprintf("[Private][%s]: %s\n", message.sender, message.content)) | |
client.writer.Flush() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment