websocket 增加多分组 fork https://github.com/olahol/melody
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Ola Holmström 8f11201a19 Store data on a per sessions basis, based on the Gin interface. 8 years ago
examples add echo example 9 years ago
.gitignore binary messages and tests 10 years ago
.travis.yml Issue #3: Add close method 10 years ago
CHANGELOG.md Store data on a per sessions basis, based on the Gin interface. 8 years ago
LICENSE license 10 years ago
README.md Store data on a per sessions basis, based on the Gin interface. 8 years ago
config.go golint 9 years ago
doc.go fix doc.go 10 years ago
envelope.go first version 10 years ago
hub.go ensure order of messages and dispatch error handler when buffer is full 10 years ago
melody.go Store data on a per sessions basis, based on the Gin interface. 8 years ago
melody_test.go Store data on a per sessions basis, based on the Gin interface. 8 years ago
session.go Store data on a per sessions basis, based on the Gin interface. 8 years ago

README.md

melody

Build Status Coverage Status GoDoc

🎶 Minimalist websocket framework for Go.

Melody is websocket framework based on github.com/gorilla/websocket that abstracts away the tedious parts of handling websockets. It gets out of your way so you can write real-time apps. Features include:

  • Clear and easy interface similar to net/http or Gin.
  • A simple way to broadcast to all or selected connected sessions.
  • Message buffers making concurrent writing safe.
  • Automatic handling of ping/pong and session timeouts.
  • Store data on sessions.

Install

go get github.com/olahol/melody

Example: chat

Chat

Using Gin:

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/olahol/melody"
	"net/http"
)

func main() {
	r := gin.Default()
	m := melody.New()

	r.GET("/", func(c *gin.Context) {
		http.ServeFile(c.Writer, c.Request, "index.html")
	})

	r.GET("/ws", func(c *gin.Context) {
		m.HandleRequest(c.Writer, c.Request)
	})

	m.HandleMessage(func(s *melody.Session, msg []byte) {
		m.Broadcast(msg)
	})

	r.Run(":5000")
}

Using Echo:

package main

import (
	"github.com/labstack/echo"
	"github.com/labstack/echo/engine/standard"
	"github.com/labstack/echo/middleware"
	"github.com/olahol/melody"
	"net/http"
)

func main() {
	e := echo.New()
	m := melody.New()

	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	e.GET("/", func(c echo.Context) error {
		http.ServeFile(c.Response().(*standard.Response).ResponseWriter, c.Request().(*standard.Request).Request, "index.html")
		return nil
	})

	e.GET("/ws", func(c echo.Context) error {
		m.HandleRequest(c.Response().(*standard.Response).ResponseWriter, c.Request().(*standard.Request).Request)
		return nil
	})

	m.HandleMessage(func(s *melody.Session, msg []byte) {
		m.Broadcast(msg)
	})

	e.Run(standard.New(":5000"))
}

Example: gophers

Gophers

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/olahol/melody"
	"net/http"
	"strconv"
	"strings"
	"sync"
)

type GopherInfo struct {
	ID, X, Y string
}

func main() {
	router := gin.Default()
	mrouter := melody.New()
	gophers := make(map[*melody.Session]*GopherInfo)
	lock := new(sync.Mutex)
	counter := 0

	router.GET("/", func(c *gin.Context) {
		http.ServeFile(c.Writer, c.Request, "index.html")
	})

	router.GET("/ws", func(c *gin.Context) {
		mrouter.HandleRequest(c.Writer, c.Request)
	})

	mrouter.HandleConnect(func(s *melody.Session) {
		lock.Lock()
		for _, info := range gophers {
			s.Write([]byte("set " + info.ID + " " + info.X + " " + info.Y))
		}
		gophers[s] = &GopherInfo{strconv.Itoa(counter), "0", "0"}
		s.Write([]byte("iam " + gophers[s].ID))
		counter += 1
		lock.Unlock()
	})

	mrouter.HandleDisconnect(func(s *melody.Session) {
		lock.Lock()
		mrouter.BroadcastOthers([]byte("dis "+gophers[s].ID), s)
		delete(gophers, s)
		lock.Unlock()
	})

	mrouter.HandleMessage(func(s *melody.Session, msg []byte) {
		p := strings.Split(string(msg), " ")
		lock.Lock()
		info := gophers[s]
		if len(p) == 2 {
			info.X = p[0]
			info.Y = p[1]
			mrouter.BroadcastOthers([]byte("set "+info.ID+" "+info.X+" "+info.Y), s)
		}
		lock.Unlock()
	})

	router.Run(":5000")
}

More examples

Documentation

Contributors

FAQ

If you are getting a 403 when trying to connect to your websocket you can change allow all origin hosts:

m := melody.New()
m.Upgrader.CheckOrigin = func(r *http.Request) bool { return true }