package main import ( "fmt" "io" "log" "golang.org/x/net/websocket" ) const channelBufSize = 100 // Chat client. type Client struct { id string ws *websocket.Conn server *Server ch chan *Message doneCh chan bool } // Create new chat client. func NewClient(ws *websocket.Conn, server *Server) *Client { if ws == nil { panic("ws cannot be nil") } if server == nil { panic("server cannot be nil") } ch := make(chan *Message, channelBufSize) doneCh := make(chan bool) clientID := getClientIDFromRequest(ws.Request()) return &Client{clientID, ws, server, ch, doneCh} } func (c *Client) Conn() *websocket.Conn { return c.ws } func (c *Client) Write(msg *Message) { select { case c.ch <- msg: default: c.server.Del(c) err := fmt.Errorf("client %d is disconnected.", c.id) c.server.Err(err) } } func (c *Client) Done() { c.doneCh <- true } // Listen Write and Read request via chanel func (c *Client) Listen() { go c.listenWrite() c.listenRead() } // Listen write request via chanel func (c *Client) listenWrite() { for { select { // send message to the client case msg := <-c.ch: log.Println("Send:", msg) websocket.JSON.Send(c.ws, msg) // receive done request case <-c.doneCh: c.server.Del(c) c.doneCh <- true // for listenRead method return } } } // Listen read request via chanel func (c *Client) listenRead() { for { select { // receive done request case <-c.doneCh: c.server.Del(c) c.doneCh <- true // for listenWrite method return // read data from websocket connection default: var msg Message err := websocket.JSON.Receive(c.ws, &msg) if err == io.EOF { c.doneCh <- true } else if err != nil { c.server.Err(err) } else { c.server.SendAll(&msg) } } } }