ws icon indicating copy to clipboard operation
ws copied to clipboard

got error message "control frame is not final" when using websocketUtil.ReadServerText

Open Jekinnnnnn opened this issue 4 years ago • 1 comments

client side:

func startTest(c *gin.Context) {
	type Request struct {
		Cnt int
		Url string
	}
	req := new(Request)
	if err := c.ShouldBind(req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"Errcode": errno.ErrWrongParam.Code(),
			"Errmsg":  errno.ErrWrongParam.Error(),
		})
		return
	}
	statistics := make([]chan int, req.Cnt)
	for i := 0; i < req.Cnt; i++ {
		statistics[i] = make(chan int)
		go func(index int, url string, res chan int) {
			conn, _, _, err := websocket.DefaultDialer.Dial(context.Background(), url)
			if err != nil {
				log.Println("dial fail index = ", index)
				res <- 1
				return
			}
			defer conn.Close()
			text := "hello world"
			err = websocketUtil.WriteClientMessage(conn, websocket.OpText, []byte(text))
			if err != nil {
				log.Println("WriteMessage failed 111:", err)
				res <- 2
				return
			}

			message, err := websocketUtil.ReadServerText(conn)
			if err != nil {
				log.Println("ReadMessage failed 222:", err)
				res <- 3
				return
			}
			log.Println("ReadMessage :", string(message))
			sleepSec := rand.Int31n(40)
			log.Println("start sleep =", sleepSec, " s")
			time.Sleep(time.Duration(sleepSec) * time.Second)
			res <- 4
		}(i, req.Url, statistics[i])
	}
	dialFailCnt := float64(0)
	writeFailCnt := float64(0)
	readFailCnt := float64(0)
	finishCnt := float64(0)
	for _, ch := range statistics {
		res := <-ch
		switch res {
		case 1:
			dialFailCnt++
		case 2:
			writeFailCnt++
		case 3:
			readFailCnt++
		case 4:
			finishCnt++
		}
	}
	floatTotal := float64(req.Cnt)
	log.Println(fmt.Sprintf("total=%d,dialFailRate=%f,writeFailRate=%f,readFailRate=%f,successRate=%f", req.Cnt, dialFailCnt/floatTotal, writeFailCnt/floatTotal, readFailCnt/floatTotal, finishCnt/floatTotal))
}

server side:

func readClientData(Conn *net.Conn) {
	for {
		message, msgType, err := websocketUtil.ReadClientData(Conn)
		if err != nil {
			break
		}
        if msgType == websocket.OpText {
			_ = websocketUtil.WriteServerMessage(Conn, msgType, []byte("send echo"))
        }
	}
}

i start a benchmark test in my 4c8g machine with code above,(obviously i removed some project-related code) when i test 5000 connection got result total=5000,dialFailRate=0.000000,writeFailRate=0.000000,readFailRate=0.004600,successRate=0.995400 all realFail errors are control frame is not final. it's a bug or my wrong usage? besides, after upgrading websocket, i bind a unique id with each connection which has lock competition that raising high cpu load, but according to the statistical results, it seems irrelevant to the question.

Jekinnnnnn avatar Aug 06 '21 02:08 Jekinnnnnn

now server detect closed websocket by matching message "^ws closed:" which return from websocketUtil.ReadClientData is there has a better way to do this?

Jekinnnnnn avatar Aug 06 '21 07:08 Jekinnnnnn