मुझे टीसीपी पैकेट पढ़ने में कुछ समस्याएं आ रही हैं।

मैं एक JSON प्रतिक्रिया पढ़ने की कोशिश कर रहा हूं, जो आकार में 5000 बाइट्स है, लेकिन Wireshark में पैकेट को देखते हुए, वे तीन अलग-अलग पैकेटों में विभाजित हैं, पहला और दूसरा 1448 बाइट्स, और तीसरा आकार में 2530 बाइट्स है।

जब मैं उन्हें Tokio-rs के साथ पढ़ने का प्रयास करता हूं, तो मुझे केवल पहला प्राप्त होता है, इसलिए मुझे संपूर्ण JSON डेटा प्राप्त नहीं होता है।

पढ़ने के लिए, मैं निम्नलिखित कोड का उपयोग कर रहा हूँ:

pub async fn read(stream: &mut TcpStream) -> Result<Bytes, std::io::Error>{
    let mut buf = BytesMut::with_capacity(8128);
    let mut resp = [0u8; 8128];
    let buf_len = stream.read(&mut resp).await?;
    buf.extend_from_slice(&resp);
    buf.truncate(buf_len);
    println!("{}", buf.len());
    Ok(buf.freeze())
}

और buf.len(), 1448 लौटाता है, जो बिल्कुल पहले और दूसरे पैकेट के आकार का होता है, लेकिन buf में पहले पैकेट का डेटा होता है।

अब मैं सोच रहा हूं कि क्या मुझे कुछ याद आया और TcpStream पहले प्राप्त पैकेट के साथ बंद हो गया या क्या मुझे कहीं बफर आकार याद आ रहा है।

0
MG lolenstine 18 अप्रैल 2020, 20:33

1 उत्तर

सबसे बढ़िया उत्तर

पढ़ने के तरीके, जैसे Read::read< /a> या AsyncReadExt::read, आम तौर पर इस बारे में कुछ भी गारंटी नहीं देता है कि प्रत्येक पर कितना डेटा खपत होगा। यदि TcpStream के पास तीन पैकेट उपलब्ध हैं, तो वह केवल पहले पैकेट, या पहले दो पैकेट, या पहले पैकेट और दूसरे के आधे पैकेट का उपभोग कर सकता है। यह जो कुछ भी करता है वह एक कार्यान्वयन विवरण है। आप केवल एक ही धारणा बना सकते हैं कि यदि यह 0 लौटाता है (यानी कोई बाइट नहीं पढ़ा गया), तो यह अपने "स्ट्रीम के अंत" तक पहुंच गया है (उदाहरण के लिए क्योंकि कनेक्शन बंद था)।

इस वजह से, आपको आम तौर पर एक लूप में पढ़ना चाहिए:

let mut buf = BytesMut::with_capacity(8128);
let mut resp = [0u8; 8128];

loop {
    let buf_len = stream.read(&mut resp).await?;
    buf.extend_from_slice(&resp[0..buf_len]);

    if buf_len == 0 {
      // end of stream
      panic!("Unexpected EOF");
    } else if buf.len() >= 5000 {
      //      ^---------------^
      //               \_________ some condition to check if buffer is "ready"

      // buffer has been filled with enough bytes
      break;
    } else {
      // buffer does not have enough bytes, keep reading...
      continue;
    }
}

println!("{}", buf.len());
Ok(buf.freeze())

वैकल्पिक रूप से, यदि आप संपूर्ण बफ़र भरना चाहते हैं, तो आप read_exact मेथड, जो बफर भर जाने तक आपके लिए लूप में पढ़ेगा, या read_to_end, जो स्ट्रीम के अंत तक पढ़ेगा।

2
Frxstrem 18 अप्रैल 2020, 18:55