> 經常項目中會用到聊天室或者游戲通訊以及服務端之間的長連接通訊,會用到websocket,以下做了一個簡單的演示效果
[TOC]
## 服務端代碼 (main.go)
~~~
package main
import (
"fmt"
"github.com/gorilla/websocket"
"net/http"
"time"
)
var upgrade = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
return true
}}
func wsHandler(w http.ResponseWriter, r *http.Request) {
var wsConn *websocket.Conn
var err error
var data []byte
if wsConn, err = upgrade.Upgrade(w, r, nil); err != nil {
return
}
go func() {
for {
if err = wsConn.WriteMessage(websocket.TextMessage, []byte("heartbeat")); err != nil {
return
}
time.Sleep(1 * time.Second)
}
}()
for {
if _, message, err = wsConn.ReadMessage(); err != nil {
wsConn.Close()
fmt.Println("wsConn is closed")
break
}
fmt.Println("response to client", message)
if string(message) == "ping" {
message = []byte("pong")
}
if err = wsConn.WriteMessage(websocket.TextMessage, message); err != nil {
wsConn.Close()
fmt.Println("wsConn2 is closed")
break
}
}
}
func main() {
//http標準庫
http.HandleFunc("/ws", wsHandler)
http.ListenAndServe("0.0.0.0:5555", nil)
}
~~~
## HTML代碼 (client.html)
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
window.addEventListener("load", function(evt) {
var output = document.getElementById("output");
var input = document.getElementById("input");
var ws;
var print = function(message) {
var d = document.createElement("div");
d.innerHTML = message;
output.appendChild(d);
};
document.getElementById("open").onclick = function(evt) {
if (ws) {
return false;
}
ws = new WebSocket("ws://localhost:5555/ws");
ws.onopen = function(evt) {
print("OPEN");
}
ws.onclose = function(evt) {
print("CLOSE");
ws = null;
}
ws.onmessage = function(evt) {
print("RESPONSE: " + evt.data);
}
ws.onerror = function(evt) {
print("ERROR: " + evt.data);
}
return false;
};
document.getElementById("send").onclick = function(evt) {
if (!ws) {
return false;
}
print("SEND: " + input.value);
ws.send(input.value);
return false;
};
document.getElementById("close").onclick = function(evt) {
if (!ws) {
return false;
}
ws.close();
return false;
};
});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<form>
<button id="open">Open</button>
<button id="close">Close</button>
<input id="input" type="text" value="Hello world!">
<button id="send">Send</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
~~~
> 本程序代碼簡化自
> channel線程安全封裝方式
> https://www.iteye.com/blog/wangking0717-2518522
> http://www.topgoer.com/%E5%85%B6%E4%BB%96/%E5%B0%81%E8%A3%85websocket.html
> beego websocket:
> https://blog.csdn.net/u012210379/article/details/72912056
- 基礎知識
- 開發環境
- 包名規則
- 包初始化 (init)
- 基礎數據類型
- 基礎類型轉換
- 格式化輸出
- go指針
- 流程控制語句
- 函數定義
- 匿名函數
- 數組和切片
- map集合
- 結構體
- Interface接口
- 日期處理
- 數學計算
- 正則表達式
- 協程 (并發處理)
- channel
- waitgroup
- mutex (鎖機制)
- websocket
- protobuf
- Redis
- 錯誤處理
- 打包程序
- NSQ消息隊列
- 單元測試
- beego
- 安裝入門
- Gin
- 快速入門
- 路由與控制器
- 處理請求參數
- 表單驗證
- 處理響應結果
- 渲染HTML模版
- 訪問靜態文件
- Gin中間件
- Cookie處理
- Session處理
- Gin上傳文件
- swagger
- pprof性能測試
- GORM
- 入門教程
- 模型定義
- 數據庫連接
- 插入數據
- 查詢數據
- 更新數據
- 刪除數據
- 事務處理
- 關聯查詢
- 屬于 (BELONG TO)
- 一對一 (Has One)
- 一對多 (Has Many)
- 多對多 (Many to Many)
- 預加載 (Preloading)
- 錯誤處理
- 第三方常用插件
- viper 讀取配置文件
- zap 高性能日志
- Nginx代理配置
- Goland 快捷鍵