Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "net/http"
- "fmt"
- "github.com/gorilla/websocket"
- "log"
- "strings"
- "sync"
- )
- type WebSocketServer struct {
- register chan *Client
- unregister chan *Client
- clients map[*Client]bool
- broadcast chan []byte
- }
- func (ws *WebSocketServer) Run() {
- for {
- select {
- case client, isOk := <- ws.register:
- if !isOk {
- log.Fatal("channel is closed, exiting")
- }
- ws.broadcast <- []byte(fmt.Sprintf("client %v joined\n", client.Name()))
- ws.clients[client] = true
- fmt.Printf("player %v joined\n", client)
- case client, isOk := <- ws.unregister:
- if !isOk {
- log.Fatal("channel is closed, exiting")
- }
- delete(ws.clients, client)
- close(client.send)
- ws.broadcast <- []byte(fmt.Sprintf("client %v left\n", client.Name()))
- fmt.Printf("player %v left\n", client)
- case msg, isOk := <- ws.broadcast:
- if !isOk {
- log.Fatal("channel is closed, exiting")
- }
- for client, _ := range ws.clients {
- client.send <- msg
- fmt.Println(client)
- }
- fmt.Printf("broadcasting msg: %v\n", string(msg))
- }
- }
- }
- type Client struct{
- server *WebSocketServer
- ws *websocket.Conn
- lock *sync.Mutex
- send chan []byte
- name string
- }
- func (c *Client) Name() string {
- c.lock.Lock()
- name := c.name
- c.lock.Unlock()
- return name
- }
- func (c *Client) SetName(name string) bool {
- c.lock.Lock()
- oldName := c.name
- c.lock.Unlock()
- if oldName == name || strings.TrimSpace(name) == "" {
- return false
- }
- c.lock.Lock()
- c.name = name
- c.lock.Unlock()
- return true
- }
- func (c *Client) read() {
- defer func() {
- c.server.unregister <- c
- c.ws.Close()
- fmt.Printf("exit read for %v\n", c.Name())
- }()
- for {
- _, msg, err := c.ws.ReadMessage()
- if err != nil {
- fmt.Println(err)
- return
- }
- if strings.HasPrefix(string(msg), "name:") {
- name := strings.SplitN(string(msg), ":", 2)[1]
- name = strings.TrimSpace(name)
- oldName := c.Name()
- if ok := c.SetName(name); ok {
- c.server.broadcast <- []byte(fmt.Sprintf("user %v changed name to %v\n", oldName, name))
- }
- continue
- }
- c.server.broadcast <- []byte(fmt.Sprintf("%v: %s\n", c.Name(), msg))
- }
- }
- func (c *Client) write() {
- defer func() {
- c.ws.Close()
- fmt.Printf("exit write for %v\n", c)
- }()
- for {
- select {
- case msg, ok := <- c.send:
- if !ok {
- return
- }
- err := c.ws.WriteMessage(websocket.TextMessage, msg)
- if err != nil {
- fmt.Println(err)
- return
- }
- }
- }
- }
- func main() {
- server := &WebSocketServer{
- register: make(chan *Client),
- unregister: make(chan *Client),
- clients: make(map[*Client]bool),
- broadcast: make(chan []byte, 1),
- }
- go server.Run()
- wsUpgrader := websocket.Upgrader{
- WriteBufferSize: 1024,
- ReadBufferSize: 1024,
- }
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- http.ServeFile(w, r, "static/index.html")
- })
- http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
- wsCon, err := wsUpgrader.Upgrade(w,r,nil)
- if err != nil {
- fmt.Println(err)
- return
- }
- client := &Client{
- server: server,
- ws: wsCon,
- send:make(chan []byte),
- lock : &sync.Mutex{},
- }
- client.name = fmt.Sprintf("%v", client)
- go client.read()
- go client.write()
- client.server.register <- client
- })
- fmt.Println(http.ListenAndServe(":8080", nil))
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement