之前使用pusher.com提供的商业服务器,但在我的站速度慢,消息传递有丢失情况,所以自行构架
主要实现通知功能:
1. 根据每个page的 session_id来区分连接,数组方式存放,应对当一个session打开了多个page的情形
2.json格式进行通讯,数据中指定要通知的session,该session下的所有page将收到通知,session_id至少做md5处理
package main
import (
"flag"
"fmt"
"net/http"
"code.google.com/p/go.net/websocket")
var port *int = flag.Int("p", 443, "Port to listen.")
//创建全局map,可以为sess_id,value为ws数组(指针)
var conns = make(map[string][]*websocket.Conn)
//type Msg struct {
// Sender string
// Receiver string
// Command string
// Data map(string)interface{}
//}
// jsonServer echoes back json string sent from client using websocket.JSON.
func server(ws *websocket.Conn) {
defer ws.Close()
req := ws.Request()
req.ParseForm()
//client := req.FormValue("client")
sess_id := req.FormValue("sess_id");
//ver := req.FormValue("ver")
//其它地方发起一个通知请求,按要求进行处理
//登记连接
if client, ok := conns[sess_id]; !ok {
conns[sess_id] = []*websocket.Conn{ws}
} else {
conns[sess_id] = append(client, ws)
}
//ws_list, _ := conns[sess_id]
//ws_list[1] = ws
//defer delete(conns, sess_id)
for {
// Receive receives a text message serialized T as JSON.
var msg map[string]interface{}
err := websocket.JSON.Receive(ws, &msg)
if err != nil {
fmt.Println(err)
break
}
fmt.Printf("recv:%#v\n", msg)
// Send send a text message serialized T as JSON.
var receiver string
for k,v := range msg {
if k == "Receiver" {
receiver = v.(string)
}
}
if receiver_ws_list, ok := conns[receiver]; ok {
//fmt.Printf("sess client count: %#i\n", len(receiver_ws_list))
for _, receiver_ws := range receiver_ws_list {
err = websocket.JSON.Send(receiver_ws, msg)
if (err != nil) {
fmt.Println("failed to send!")
}
}
fmt.Println("sended!")
}
if err != nil {
fmt.Println(err)
break
}
fmt.Printf("send:%#v\n", msg)
}
my_ws_list, _ := conns[sess_id]
for i, my_ws := range my_ws_list {
if my_ws == ws {
conns[sess_id] = append(my_ws_list[:i], my_ws_list[i+1:]...)
fmt.Printf("a client removed\n")
}
}
//remove ws form slice
fmt.Printf("a client closed\n")
}
func main() {
flag.Parse()
http.Handle("/", websocket.Handler(server))
fmt.Printf("http://localhost:%d/\n", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
if err != nil {
panic("ListenANdServe: " + err.Error())
}
}