func (c *client) NextReader() (*parser.PacketDecoder, error) { var reader io.Reader for { t, r, err := c.conn.NextReader() if err != nil { return nil, err } switch t { case websocket.TextMessage: fallthrough case websocket.BinaryMessage: reader = r return parser.NewDecoder(reader) } } }
func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) { defer s.callback.OnClose(s) for { t, r, err := s.conn.NextReader() if err != nil { s.conn.Close() return } switch t { case websocket.TextMessage: fallthrough case websocket.BinaryMessage: decoder, err := parser.NewDecoder(r) if err != nil { return } s.callback.OnPacket(decoder) decoder.Close() } } }
func TestConnIoutil(t *testing.T) { Convey("Reader", t, func() { Convey("Normal read", func() { r := bytes.NewBufferString("\x34\xe6\xb5\x8b\xe8\xaf\x95") decoder, err := parser.NewDecoder(r) So(err, ShouldBeNil) closeChan := make(chan struct{}) reader := newConnReader(decoder, closeChan) b := make([]byte, 1024) n, err := reader.Read(b) So(err, ShouldBeNil) So(string(b[:n]), ShouldEqual, "测试") n, err = reader.Read(b) So(err, ShouldEqual, io.EOF) Convey("Wait close", func() { check := make(chan int) go func() { err := reader.Close() if err != nil { t.Fatal(err) } check <- 1 }() time.Sleep(time.Second / 10) // wait goroutine start select { case <-check: So("should not run here", ShouldEqual, "") default: } <-closeChan time.Sleep(time.Second / 10) // wait goroutine end select { case <-check: default: So("should not run here", ShouldEqual, "") } Convey("Close again", func() { err := reader.Close() So(err, ShouldBeNil) }) }) }) }) Convey("Wrtier", t, func() { Convey("Normal write", func() { locker := sync.Mutex{} w := bytes.NewBuffer(nil) locker.Lock() writer := newConnWriter(writeCloser{w}, &locker) _, err := writer.Write([]byte("abc")) So(err, ShouldBeNil) So(w.String(), ShouldEqual, "abc") writer.Close() }) Convey("Sync", func() { locker := sync.Mutex{} w1 := bytes.NewBuffer(nil) locker.Lock() writer1 := newConnWriter(writeCloser{w1}, &locker) check := make(chan int) go func() { w2 := bytes.NewBuffer(nil) locker.Lock() writer2 := newConnWriter(writeCloser{w2}, &locker) defer writer2.Close() check <- 1 }() time.Sleep(time.Second / 10) select { case <-check: So("should not run here", ShouldEqual, "") default: } err := writer1.Close() So(err, ShouldBeNil) time.Sleep(time.Second / 10) // wait goroutine end select { case <-check: default: So("should not run here", ShouldEqual, "") } Convey("Close again", func() { err := writer1.Close() So(err, ShouldBeNil) }) }) }) }