Golang 实现 websocket 通讯(一个服务器,两个客户端)

运行客户端时首先要输入自己的名字,两个客户端输入的名字不能一样。

先上运行结果:

服务器端:

客户端1:

客户端2:

话不多说,直接上代码:

服务器端:

Go 复制代码
package main

import (
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
)

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

// Client represents a connected client
type Client struct {
	conn *websocket.Conn
}

// Message represents a message from a client
type Message struct {
	Sender    string `json:"sender"`
	Recipient string `json:"recipient"`
	Content   string `json:"content"`
}

var clients = make(map[*Client]bool)
var broadcast = make(chan Message)

func handleConnections(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()

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

	fmt.Println("Client connected")

	for {
		var msg Message
		err := conn.ReadJSON(&msg)
		if err != nil {
			log.Println(err)
			delete(clients, client)
			break
		}

		broadcast <- msg
	}
}

func handleMessages() {
	for {
		msg := <-broadcast

		for client := range clients {
			if client.conn != nil {
				err := client.conn.WriteJSON(msg)
				if err != nil {
					log.Println(err)
					client.conn.Close()
					delete(clients, client)
				}
			}
		}
	}
}

func main() {
	http.HandleFunc("/", handleConnections)
	go handleMessages()

	fmt.Println("WebSocket server listening on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

客户端1:

Go 复制代码
package main

import (
	"bufio"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"os"
)

type Message struct {
	Sender    string `json:"sender"`
	Recipient string `json:"recipient"`
	Content   string `json:"content"`
}

func main() {
	conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080", nil)
	if err != nil {
		log.Println("Error connecting to server:", err)
		return
	}
	defer conn.Close()

	go func() {
		for {
			var msg Message
			err := conn.ReadJSON(&msg)
			if err != nil {
				log.Println("Error reading message:", err)
				return
			}
			fmt.Printf("Received from %s: %s\n", msg.Sender, msg.Content)
		}
	}()

	fmt.Print("Enter your name: ")
	var name string
	fmt.Scanln(&name)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		message := scanner.Text()
		msg := Message{Sender: name, Content: message}
		err := conn.WriteJSON(msg)
		if err != nil {
			log.Println("Error sending message:", err)
			return
		}
	}
}

客户端2:

Go 复制代码
package main

import (
	"bufio"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"os"
)

type Message struct {
	Sender    string `json:"sender"`
	Recipient string `json:"recipient"`
	Content   string `json:"content"`
}

func main() {
	conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080", nil)
	if err != nil {
		log.Println("Error connecting to server:", err)
		return
	}
	defer conn.Close()

	go func() {
		for {
			var msg Message
			err := conn.ReadJSON(&msg)
			if err != nil {
				log.Println("Error reading message:", err)
				return
			}
			fmt.Printf("Received from %s: %s\n", msg.Sender, msg.Content)
		}
	}()

	fmt.Print("Enter your name: ")
	var name string
	fmt.Scanln(&name)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		message := scanner.Text()
		msg := Message{Sender: name, Content: message}
		err := conn.WriteJSON(msg)
		if err != nil {
			log.Println("Error sending message:", err)
			return
		}
	}
}
相关推荐
Boop_wu4 小时前
[Java 算法] 字符串
linux·运维·服务器·数据结构·算法·leetcode
m0_694845575 小时前
Dify部署教程:从AI原型到生产系统的一站式方案
服务器·人工智能·python·数据分析·开源
yangyanping201085 小时前
Go语言学习之对象关系映射GORM
jvm·学习·golang
码云数智-大飞5 小时前
C++ RAII机制:资源管理的“自动化”哲学
java·服务器·php
白毛大侠6 小时前
理解 Go 接口:eface 与 iface 的区别及动态性解析
开发语言·网络·golang
SkyXZ~6 小时前
Jetson有Jtop,Linux有Htop,RDK也有Dtop!
linux·运维·服务器·rdkx5·rdks100·dtop
黑牛儿7 小时前
MySQL 索引实战详解:从创建到优化,彻底解决查询慢问题
服务器·数据库·后端·mysql
杨云龙UP8 小时前
Oracle Data Pump实战:expdp/impdp常用参数与导入导出命令整理_20260406
linux·运维·服务器·数据库·oracle
想唱rap8 小时前
线程池以及读写问题
服务器·数据库·c++·mysql·ubuntu
萌萌哒草头将军9 小时前
CloudDock(云仓):新一代开源NAS网络代理工具
服务器·网络协议·docker