golang websocket的例子

最近写了一个chrome的websocket extension,server端用的是Java的Netty框架,后来发现golang 实现websocket 非常简单,高效, 下面是例子, 简单实现了用户登录,广播,相当于聊天室!


package main

import (
	"code.google.com/p/go.net/websocket"
	"html/template"
	"log"
	"net/http"
	"os"
	"strings"
	"time"
)

const (
	listenAddr = "localhost:9527" // server address
)

var (
	pwd,_        = os.Getwd()
	RootTemp      = template.Must(template.ParseFiles(pwd + "/chat.html"))
	JSON          = websocket.JSON              // codec for JSON
	Message       = websocket.Message           // codec for string,[]byte
	ActiveClients = make(map[ClientConn]string) // map containing clients
	User          = make(map[string]string)
)

// Initialize handlers and websocket handlers
func init() {
	User["aaa"] = "aaa"
	User["bbb"] = "bbb"
	User["test"] = "test"
	User["test2"] = "test2"
	User["test3"] = "test3"
}

// Client connection consists of the websocket and the client ip
type ClientConn struct {
	websocket *websocket.Conn
	clientIP  string
}

// WebSocket server to handle chat between clients
func SockServer(ws *websocket.Conn) {
	var err error
	var clientMessage string
	// use []byte if websocket binary type is blob or arraybuffer
	// var clientMessage []byte

	// cleanup on server side
	defer func() {
		if err = ws.Close(); err != nil {
			log.Println("Websocket could not be closed",err.Error())
		}
	}()

	client := ws.Request().RemoteAddr
	log.Println("Client connected:",client)
	sockCli := ClientConn{ws,client}
	ActiveClients[sockCli] = ""
	log.Println("Number of clients connected:",len(ActiveClients))

	// for loop so the websocket stays open otherwise
	// it'll close after one Receieve and Send
	for {
		if err = Message.Receive(ws,&clientMessage); err != nil {
			// If we cannot Read then the connection is closed
			log.Println("Websocket Disconnected waiting",err.Error())
			// remove the ws client conn from our active clients
			delete(ActiveClients,sockCli)
			log.Println("Number of clients still connected:",len(ActiveClients))
			return
		}

		var msg_arr = strings.Split(clientMessage,"|")
		if msg_arr[0] == "login" && len(msg_arr) == 3 {
			name := msg_arr[1]
			pass := msg_arr[2]

			if pass == User[name] {
				ActiveClients[sockCli] = name

				if err = Message.Send(ws,"login|"+name); err != nil {
					log.Println("Could not send message to ",client,err.Error())
				}
			} else {
				log.Println("login faild:",clientMessage)
			}

		} else if msg_arr[0] == "msg" {
			if ActiveClients[sockCli] != "" {
				clientMessage = "msg|" + time.Now().Format("2006-01-02 15:04:05") + " " + ActiveClients[sockCli] + " Said: " + msg_arr[1]
				for cs,na := range ActiveClients {
					if na != "" {
						if err = Message.Send(cs.websocket,clientMessage); err != nil {
							log.Println("Could not send message to ",cs.clientIP,err.Error())
						}
					}
				}
			}
		}
	}
}

// RootHandler renders the template for the root page
func RootHandler(w http.ResponseWriter,req *http.Request) {
	err := RootTemp.Execute(w,listenAddr)
	if err != nil {
		http.Error(w,err.Error(),http.StatusInternalServerError)
	}
}

func main() {
	http.HandleFunc("/",RootHandler)
	http.Handle("/socket",websocket.Handler(SockServer))
	err := http.ListenAndServe(listenAddr,nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}

相关文章

程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息...
本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简...
简介 默克尔树(MerkleTree)是一种典型的二叉树结构,其主要特点为: 最下面的叶节点包含存储数据或其...
接下来学习并发编程, 并发编程是go语言最有特色的地方, go对并发编程是原生支持. goroutine是go中最近本...
先普及一下, 什么是广度优先搜索 广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶...
第一天: 接口的定义和实现 第二天: 一. go语言是面向接口编程. 在学习继承的时候说过, go语言只有封装,...