Skip to content

Instantly share code, notes, and snippets.

@M0nteCarl0
Last active July 31, 2023 10:41
Show Gist options
  • Save M0nteCarl0/55228c4bd18167019135c6f8540ce1ee to your computer and use it in GitHub Desktop.
Save M0nteCarl0/55228c4bd18167019135c6f8540ce1ee to your computer and use it in GitHub Desktop.
Simple TCP chat client and server with private messages for connected users
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")
}
}
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