最近被后台日志弄的很烦,看到有个项目简简单单,又能知足须要,顺便试下看看效果,作下记录。只是记录下一部份内容,就不所有读了,关于源码能够去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()