假设我们尝试与发送回XML数据的服务器(XMPP)通信。我们可以用
conn, err := net.Dial("tcp", s.Addr+":5222") //... r := bufio.NewReader(conn) //... s, err := s.R.ReadString(10) // to read a string
但是存在一个问题,即服务器不发送\ 10(换行符)符号。我也尝试了12次,但是没有任何运气。readLine函数也是如此,因为它也依赖\ 10。那么,如何读取服务器发送的数据?我尝试使用“>”作为分隔符,并成功仅接收了部分消息(可预测)。我有一个在错误为nil时循环并使用’>’分隔符的想法,但它也没有用。我的研究表明,该消息的最后一个符号实际上是’>’(62),并且末尾没有其他任何内容。
使用xml.Decoder从XMPP流中读取节。
conn, err := net.Dial("tcp", s.Addr+":5222") if err != nil { // handle error } dec := xml.NewDecoder(conn)
使用解码器Token方法读取根文档元素,并跳过节之间的字符数据:
func readStartElement(dec *xml.Decoder) (xml.StartElement, error) { for { t, err := dec.Token() if err != nil { return xml.StartElement{}, err } switch t := t.(type) { case xml.StartElement: return t, nil } } }
使用解码器的DecodeElement方法读取一个节:
func readStanza(dec *xml.Decoder) (interface{}, error) { se, err := readStartElement(dec) if err != nil { return nil, err } var v interface{} switch se.Name.Space + " " + se.Name.Local { case "jabber:client message": v = &jabberMessage{} // jabberMessage is struct type defined by app for messages // Add other stanza types here. default: v = &struct{}{} } if err := dec.DecodeElement(v, &se); err != nil { return nil, err } return v, nil }
在readStanza的返回值上输入类型开关,以处理不同类型的已接收节。
客户端同步读取节。这是一个粗略的轮廓(忽略身份验证等)。
conn, err := net.Dial("tcp", s.Addr+":5222") if err != nil { // handle error } dec := xml.NewDecoder(conn) // read and discard root element _, err := readStartElement(dec) if err != nil { // handle error } // read stanzas for { v, err := readStanza(dec) if err != nil { // handle error // must break out of loop on error } switch v := v.(type) { case *jabberMessage: // handle message case *someOtherStanzaType: // handle other stanza types // ... and so on } }