Creating a Multi-Room Chat Server with Go and WebSockets

Table of Contents

  1. Overview
  2. Prerequisites
  3. Setup
  4. Creating the Chat Server
  5. Building the Frontend
  6. Testing
  7. Conclusion

Overview

In this tutorial, we will create a multi-room chat server using Go and WebSockets. The chat server will allow multiple clients to join different chat rooms and communicate with each other in real-time. By the end of this tutorial, you will have a fully functional chat server with a web-based frontend.

Prerequisites

Before starting this tutorial, you should have a basic understanding of Go programming language and web development concepts. Familiarity with the command line and Go tools is also recommended.

Setup

To create our multi-room chat server, we will make use of the gorilla/websocket package, which provides a WebSocket implementation for Go. To install this package and its dependencies, run the following command in your terminal:

go get github.com/gorilla/websocket

Creating the Chat Server

Let’s start by creating the main file for our chat server. Create a file named main.go and add the following code:

package main

import (
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

type Client struct {
	conn *websocket.Conn
}

func (c *Client) read() {
	for {
		_, _, err := c.conn.ReadMessage()
		if err != nil {
			log.Println(err)
			break
		}
	}
}

func (c *Client) write() {
	for {
		// Logic to send messages to the client
	}
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		serveHome(w, r)
	})

	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		serveWs(w, r)
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}

In this code, we define a Client struct that represents a connected client. The read method continuously reads messages from the client, and the write method sends messages to the client.

We also define two HTTP handlers: one for serving the home page and another for WebSocket connections. The serveHome function can be implemented later to serve an HTML page for the frontend. The serveWs function handles WebSocket connections and initializes a new Client for each connection.

Now, let’s implement the serveWs function. Add the following code below the main function:

var clients = make(map[*websocket.Conn]bool)

func serveWs(w http.ResponseWriter, r *http.Request) {
	upgrader := websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}

	client := &Client{conn: conn}
	clients[conn] = true

	go client.read()
	go client.write()
}

In this code, we initialize the WebSocket connection and add the client to the clients map. We then spawn two goroutines to handle reading and writing messages for this client.

The serveWs function uses the websocket.Upgrader to upgrade the HTTP connection to a WebSocket connection. The CheckOrigin function is set to allow connections from any origin, but you can modify this behavior as per your requirements.

Building the Frontend

To create the frontend of our chat server, we will use HTML, CSS, and JavaScript. Create a new file named index.html and add the following code:

<!DOCTYPE html>
<html>
<head>
	<title>Multi-Room Chat Server</title>
	<style>
		/* CSS Styles */
	</style>
	<script>
		// JavaScript Code
	</script>
</head>
<body>
	<h1>Multi-Room Chat Server</h1>
	<div id="messages"></div>
	<input type="text" id="inputMessage" placeholder="Type a message...">
	<button id="sendButton">Send</button>

	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</body>
</html>

This HTML file provides a basic structure for our chat server frontend. The messages div will display the chat messages, the inputMessage input field allows users to type messages, and the sendButton is used to send messages.

Now, let’s add the JavaScript code that handles the WebSocket connection and sends/receives messages. Add the following code in the <script> tag of index.html:

// JavaScript Code
$(document).ready(function() {
	const socket = new WebSocket("ws://localhost:8080/ws");

	socket.onopen = function() {
		console.log("WebSocket connection established.");
	};

	socket.onmessage = function(event) {
		const message = event.data;
		// Logic to display the received message
	};

	socket.onclose = function(event) {
		console.log("WebSocket connection closed.");
	};

	$("#sendButton").click(function() {
		const message = $("#inputMessage").val();
		socket.send(message);
		$("#inputMessage").val("");
	});
});

This JavaScript code establishes the WebSocket connection with our chat server, handles received messages, and sends messages when the “Send” button is clicked.

Testing

To test our multi-room chat server, first, start the server by running the following command:

go run main.go

Now, open your web browser and visit http://localhost:8080. You should see the chat interface. Open multiple tabs or browsers and join different chat rooms. Try sending messages between the clients connected to the same chat room, and you should see the messages being displayed in real-time.

Conclusion

Congratulations! You have successfully created a multi-room chat server using Go and WebSockets. You learned how to handle WebSocket connections, send/receive messages, and build a basic frontend for the chat server. Feel free to enhance the chat server by adding features like user authentication, private messaging, or message history persistence.

Remember to leverage the power of Go’s concurrency and goroutines to handle multiple clients efficiently. Also, don’t forget to properly clean up the resources when clients disconnect from the chat server.

Keep exploring different use cases and experiment with different techniques to further enhance your Go programming skills.


Frequently Asked Questions

Q: Can I make the chat server available over the internet?

A: Yes, you can deploy the chat server to a cloud provider or a server with a public IP address. Ensure to configure the required network settings and update the frontend JavaScript code with the correct server URL.

Q: How can I add user authentication to the chat server?

A: You can integrate a user authentication mechanism such as OAuth or username/password authentication at the server-side. Upon successful authentication, you can assign a unique identifier to each client and store additional user information for further functionality.

Q: Is it possible to send multimedia messages through the chat server?

A: Yes, you can extend the chat server to support multimedia messages. You can either encode the multimedia files as Base64 strings and send them as regular text messages or implement file uploads and share the download links in the chat.