zinx icon indicating copy to clipboard operation
zinx copied to clipboard

读取链接流,使用Scanner建议

Open hessonsu opened this issue 2 years ago • 1 comments

目前的读取数据。似乎无解决粘包问题! 改进建议: 24是我这边协议的包头长度。

func (c *Connection) StartReader() {
	dataPacker := NewDataPack()
	scanner := bufio.NewScanner(c.Conn)
	buf := make([]byte, 24)
	scanner.Buffer(buf, bufio.MaxScanTokenSize)
	scanner.Split(c.splitPack)
	for scanner.Scan() {
		c.Conn.SetReadDeadline(time.Now().Add(utils.GlobalObject.KeepAlive))
		msg, err := dataPacker.Unpack(scanner.Bytes())
		if err != nil {
			logger.Error("unpack error ", err)
			continue
		}
		logger.Debugf("Tcp receive msg:%s", msg.GetBody())
		var jsonObj dto.Result
		json.Unmarshal(msg.GetBody(), &jsonObj)

		//得到当前客户端请求的Request数据
		req := Request{
			conn: c,
			msg:  msg,
			ret:  jsonObj,
		}

		if utils.GlobalObject.WorkerPoolSize > 0 {
			//已经启动工作池机制,将消息交给Worker处理
			c.MsgHandler.SendMsgToTaskQueue(&req)
		} else {
			//从绑定好的消息和对应的处理方法中执行对应的Handle方法
			go c.MsgHandler.DoMsgHandler(&req)
		}

	}

}
func (c *Connection) splitPack(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF {
		return 0, nil, io.EOF
	}
	// 4个字节是包头的长度
	if len(data) <= 4 {
		return 0, nil, nil
	}
	var bodySize int = (int)(binary.LittleEndian.Uint32(data))
	pkgLength := bodySize + 24 //包头长度24
	if len(data) < pkgLength {
		return 0, nil, nil
	}
	return pkgLength, data[:pkgLength], nil
}

hessonsu avatar Aug 18 '22 06:08 hessonsu

想法不错,可以提PR哈。 而且为什么说现在解决不了粘包呢,现在也是可以解决的,你这种Scanner的方式也不错。但是包头定义24,和目前客户端那个案例的协议不太符合。你还有改成8的版本的吗。

aceld avatar Aug 22 '22 10:08 aceld

粘包问题查看最新版本

xxl6097 avatar Mar 29 '23 08:03 xxl6097