原文地址:http://blog.csdn.net/wangshubo1989/article/details/78250790
使用到的golang包:gorilla/websocket
关于golang的websocket的使用,上述地址的文章讲解比较详细,大家自己去看。
在此仅记录自己的理解:
package main
import (
"fmt"
"github.com/gorilla/websocket"
GOOGLE_PROTO "github.com/golang/protobuf/proto"
"proto"
"flag"
"net/url"
"encoding/binary"
"bytes"
)
//关注该代码
var addr = flag.String("addr","localhost:57579","http service address")
func main() {
//关注该代码
u:=url.URL{Scheme:"ws",Host:*addr,Path:"/ws"}
var dialer *websocket.Dialer
//关注该代码
conn,_,err:=dialer.Dial(u.String(),nil)
if err != nil{
fmt.Println(err)
return
}
timeWriter(conn)
for {
var recvBuf []byte
//关注该代码
messageType,message,err :=conn.ReadMessage()
if err != nil{
fmt.Println("read:",err)
return
}
recvBuf = append(recvBuf, message...)
if (messageType != websocket.BinaryMessage) {
continue
}
var recvbuf_len int32
recvbuf_len = int32(len(recvBuf))
fmt.Printf("recvbuf_len=%d\n",recvbuf_len)
// 接收数据
for recvbuf_len >= PKG_HEAD_LEN { // 粘包循环处理
var head Head
buf_read := bytes.NewBuffer(recvBuf[:PKG_HEAD_LEN])
err := binary.Read(buf_read, binary.BigEndian, &head)
if err != nil {
break
}
if head.PkgFlag == ']' {
if recvbuf_len >= head.PkgLen {
if protocol.Cmd(head.PkgCmd) == protocol.Cmd_CMD_KEEPALIVE_C2S {
} else {
pkg_len := head.PkgLen - PKG_HEAD_LEN
newbuffer := make([]byte, pkg_len)
copy(newbuffer, recvBuf[PKG_HEAD_LEN:head.PkgLen])
fmt.Printf("pkg_len=%d,newbuffer=%v",pkg_len,newbuffer)
}
recvBuf = recvBuf[head.PkgLen:]
recvbuf_len = int32(len(recvBuf))
} else { // 半包,继续接收
break
}
} else { // 错误包边界。。。暂时这么处理?不过也可以直接断开连接。
fmt.Println("headflag=%d",head.PkgFlag)
fmt.Println("client read error!!!")
recvBuf = make([]byte,0)
recvbuf_len = int32(0)
}
}
}
}
func timeWriter(conn *websocket.Conn) {
conn.WriteMessage(websocket.BinaryMessage, LoginData())
conn.WriteMessage(websocket.BinaryMessage, HistData())
}
func HistData() []byte{
histData:=&protocol.ReqHist{}
histData.Gid=GOOGLE_PROTO.Int64(10000001)
pack,err :=PacketMessage(protocol.Cmd(protocol.Cmd_CMD_HIST_C2S2C),histData)
if err != nil{
fmt.Println(err.Error())
}
return pack
}
func LoginData() []byte {
loginData:=&protocol.ReqLogin{}
loginData.Token=GOOGLE_PROTO.String("123456")
pack,err :=PacketMessage(protocol.Cmd(protocol.Cmd_CMD_LOGIN_C2S2C),loginData)
if err != nil{
fmt.Println(err.Error())
}
return pack
}
以上代码是自己在做客户端模拟时写的部分测试代码,因为markdown不是很方便,代码高亮不容易实现,所以用“//关注代码”标注,这几句是websocket客户端接收和发送消息的关键代码。另外需要注意的是引用的包是"github.com/gorilla/websocket"。