Closed
Description
I just wrote a demo to test it. Here is my code:
package main
import (
"net/http"
"io"
"fmt"
"nhooyr.io/websocket"
"context"
"time"
"strconv"
)
func main(){
go func(){
http.ListenAndServe(`127.0.0.1:9098`,echoServer{})
}()
time.Sleep(time.Millisecond*10)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
c, _, err := websocket.Dial(ctx, `http://127.0.0.1:9098`, &websocket.DialOptions{
Subprotocols: []string{"echo"},
})
defer c.Close(websocket.StatusNormalClosure,``)
ctx = context.Background()
inList:=[]byte{1}
buf:=make([]byte,1024)
c2:=websocket.NetConn(ctx,c,websocket.MessageBinary)
for i:=0;i<10;i++{
_,err=c2.Write(inList)
if err!=nil{
panic(err)
}
nr,err := c2.Read(buf)
if err!=nil{
panic(err)
}
if nr==0{
panic(`nr==0 `+strconv.Itoa(i))
}
}
}
// echoServer is the WebSocket echo server implementation.
// It ensures the client speaks the echo subprotocol and
// only allows one message every 100ms with a 10 message burst.
type echoServer struct {
// logf controls where logs are sent.
logf func(f string, v ...interface{})
}
func (s echoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
Subprotocols: []string{"echo"},
})
if err != nil {
s.logf("%v", err)
return
}
defer c.Close(websocket.StatusInternalError, "the sky is falling")
if c.Subprotocol() != "echo" {
c.Close(websocket.StatusPolicyViolation, "client must speak the echo subprotocol")
return
}
for {
err = echo(r.Context(), c)
if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
return
}
if err != nil {
s.logf("failed to echo with %v: %v", r.RemoteAddr, err)
return
}
}
}
// echo reads from the WebSocket connection and then writes
// the received message back to it.
// The entire function has 10s to complete.
func echo(ctx context.Context, c *websocket.Conn) error {
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
typ, r, err := c.Reader(ctx)
if err != nil {
return err
}
w, err := c.Writer(ctx, typ)
if err != nil {
return err
}
_, err = io.Copy(w, r)
if err != nil {
return fmt.Errorf("failed to io.Copy: %w", err)
}
err = w.Close()
return err
}
And I found that websocket.NetConn().Read() will return zero and nil .
I never seen a net.Conn object work like this.
I do not know how to do with it , skip? But I am afraid of unlimit loop...
Metadata
Metadata
Assignees
Labels
No labels