GO 語言websocket程式設計
阿新 • • 發佈:2018-12-12
GO提供原生的websocket API,使用時go get然後引用即可golang.org/x/net/websocket
使用起來也很方便,直接上程式碼吧。
一個echo server的程式碼
package main import( "golang.org/x/net/websocket" "fmt" "net/http" "flag" ) type WSServer struct { ListenAddr string } func (this *WSServer)handler(conn *websocket.Conn){ fmt.Printf("a new ws conn: %s->%s\n", conn.RemoteAddr().String(), conn.LocalAddr().String()) var err error for { var reply string err = websocket.Message.Receive(conn, &reply) if err != nil { fmt.Println("receive err:",err.Error()) break } fmt.Println("Received from client: " + reply) if err = websocket.Message.Send(conn, reply); err != nil { fmt.Println("send err:", err.Error()) break } } } func (this *WSServer)start()(error){ http.Handle("/ws", websocket.Handler(this.handler)) fmt.Println("begin to listen") err := http.ListenAndServe(this.ListenAddr, nil) if err != nil { fmt.Println("ListenAndServe:", err) return err } fmt.Println("start end") return nil } func main(){ addr := flag.String("a", "127.0.1.1:12345", "websocket server listen address") flag.Parse() wsServer := &WSServer{ ListenAddr : *addr, } wsServer.start() fmt.Println("------end-------") }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
上述程式碼中,每來一個新的websocket client,server會起一個goroutine執行WSSever的handler函式。
websocket client程式碼例項
package main import ( "flag" "fmt" "time" "golang.org/x/net/websocket" ) var addr = flag.String("addr", "127.0.0.1:12345", "http service address") func main() { flag.Parse() url := "ws://"+ *addr + "/ws" origin := "test://1111111/" ws, err := websocket.Dial(url, "", origin) if err != nil { fmt.Println(err) } go timeWriter(ws) for { var msg [512]byte _, err := ws.Read(msg[:])//此處阻塞,等待有資料可讀 if err != nil { fmt.Println("read:", err) return } fmt.Printf("received: %s\n", msg) } } func timeWriter(conn *websocket.Conn) { for { time.Sleep(time.Second * 2) websocket.Message.Send(conn, "hello world") } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
client的程式碼,每隔2秒鐘傳送hello world到server,然後阻塞在Read函式。需要注意的是origin必須以“http://1111111/” 這種標準的URI格式,否則報錯“invalid URI for request”。
關閉程序、網路斷線等異常情況
關閉程序
無論server還是client,關閉程序,對端Read都會立刻收到EOF,對EOF做處理即可。
網路斷線
- 測試 client和server部署在不同機器上,client每隔2秒中向server傳送資料,server收到後回吐給客戶端。這個過程中,拔掉client的網線。
- 測試結果
- 斷網後,client一定時間內寫都能成功返回,但是因為斷網實際沒有傳送出去,資料寫到了底層tcp的緩衝區。
- 過一段時間後,1分鐘左右,client Read返回錯誤“read: operation timed out”。Write會返回“write: broken pipe”。這個可能是Go中websocket實現時加了超時機制,也有可能是設定了底層TCP SO_KEEPALIVE,檢測到了網路不可用。
- 在Read/Write返回錯誤之前,重新連上網路,可以繼續傳送和接受資料。這個可以從TCP的實現上解釋。TCP連線並不是物理連線,本質上就是連線兩端各自系統核心維護的一個四元組。客戶端斷線,在一定時間內並不會導致四元組的釋放。所以當連上網線後此TCP連線可以自動恢復,繼續進行正常的網路操作。
- 斷線重連到其他網路,相當於斷網。這個很好解釋,連上其他網路,IP地址都改變了,之前的四元組不可用。
--------------------- 本文來自 阿冬哥 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/c359719435/article/details/78845719?utm_source=copy