最近被後臺日誌弄的很煩,看到有個項目簡簡單單,又能知足須要,順便試下看看效果,作下記錄。只是記錄下一部份內容,就不所有讀了,關於源碼能夠去https://github.com/xmge/seelog。git
// websocket客戶端 type client struct { id string socket *websocket.Conn send chan []byte } // 客戶端管理 type clientManager struct { clients map[*client]bool broadcast chan []byte register chan *client unregister chan *client }
WebSocket 是 HTML5 開始提供的一種在單個 TCP 鏈接上進行全雙工通信的協議。github
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。web
在 WebSocket API 中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。數組
程序使用管道做爲通訊基礎瀏覽器
func (manager *clientManager) start() { defer func() { if err := recover(); err != nil { log.Printf("[seelog] error:%+v", err) } }() for { select { case conn := <-manager.register: manager.clients[conn] = true case conn := <-manager.unregister: if _, ok := manager.clients[conn]; ok { close(conn.send) delete(manager.clients, conn) } case message := <-manager.broadcast: for conn := range manager.clients { select { case conn.send <- message: default: close(conn.send) delete(manager.clients, conn) } } } } }
使用select-case進行管道的數據處理,外部加一個for循環保持輪詢的狀態。服務器
func (c *client) write() { defer func() { manager.unregister <- c c.socket.Close() }() for { select { case message, ok := <-c.send: if !ok { c.socket.WriteClose(1) return } c.socket.Write(message) } } }
這個是在每一個websocket啓動的時候使用,每一個socket保持一個for循環,使用defer用於關閉操做,當for被打斷(即關閉網頁之類的操做),socket被關閉,則會插入到取消管道中,clients鍵值對會刪除這個鏈接的信息。websocket
經過os.Stat獲取文件信息,返回值爲fileInfo的接口socket
fileInfo, err = os.Stat(filePath) func (f *File) Stat() (FileInfo, error) type FileInfo interface { Name() string // base name of the file 文件名 Size() int64 // length in bytes for regular files; system-dependent for others 文件大小(byte長度) Mode() FileMode // file mode bits 文件模式(只讀、只寫之類) ModTime() time.Time // modification time IsDir() bool // abbreviation for Mode().IsDir() 是不是目錄 Sys() interface{} // underlying data source (can return nil) 基礎數據源(能夠返回nil) }
獲取當前的文件的截止位置設計
offset := fileInfo.Size()
獲取新的文件大小,而後根據文件大小和以前的區別,構建一個新的byte數組,大小爲新的字節數減去舊的字節數指針
msg := make([]byte, newOffset-offset)
使用Open方法打開一個文件,Open方法是以只讀的方式讀取數據
file, err := os.Open(filePath) func Open(name string) (*File, error)
能夠將文件讀取的起點設置到某個位置,在seelog中,將讀取起點設置到文件末尾,當文件的大小發生變化,則文件從上個起點開始讀取文件內容
_, err = file.Seek(offset, 0) func (f *File) Seek(offset int64, whence int) (ret int64, err error) whence 存在3個參數 0:文件頭的絕對位置偏移offset的距離 1:文件的相對位置,即當前位置偏移offset的距離 2:文件末尾的絕對位置偏移offset的距離 這個特性當文件以O_APPEND的模式打開是沒有效果的
msg是以前構造的字節數組,將新增的內容讀取到字節數組中
_, err = file.Read(msg)
使用管道做爲消息傳輸的方式,manager在這裏是一個全局的manager,當管道收到消息,就打印處理
manager.broadcast <- msg
最後記得將文件關閉,不然下次打開會出錯
file.Close()