2016-03-19 15 views
0

Предположим, мы пытаемся связаться с сервером (XMPP), который отправляет данные XML. Мы можем использоватьКак читать данные (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 
} 

Type 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 
    } 
} 
+0

Не следует «возвращать err' быть« return nil, err'? –

+0

@ SanjayT.Sharma Это должно быть 'return xml.StartElement {}, err'. Спасибо, что указал на проблему. –