Как прочитать данные (xml), отправленные сервером, если он не отправляет новую строку
Допустим, мы пытаемся связаться с сервером (XMPP), который отправляет обратно данные XML. Мы можем использовать
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. Так как мне прочитать данные, отправленные сервером? Я попытался использовать ">" в качестве разделителя, и мне удалось получить только часть сообщений (предсказуемо). У меня была идея зациклить, пока ошибка равна нулю, и использовать разделитель '>', но это также не сработало. Мое исследование показало, что последний символ сообщения действительно '>' (62), и в конце больше ничего нет.
1 ответ
Используйте 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.DeocdeElement(v, &se); err != nil {
return nil, err
}
return v, nil
}
Введите switch на возвращаемое значение из 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
}
}