นำทางผ่านความท้าทายในการอ่านการตอบสนองแบบ chunked
ใน HttpWebResponse
เมื่อทำงานกับคำขอ HTTP ใน C# นักพัฒนาหลายคนมักพบปัญหาเมื่อพยายามอ่านการตอบสนองแบบ chunked
โดยใช้คลาส StreamReader
สถานการณ์นี้อาจนำไปสู่ความสับสนและความหงุดหงิด โดยเฉพาะอย่างยิ่งเมื่อคำขอที่คล้ายกันสำหรับการตอบสนองแบบ non-chunked
ทำงานได้โดยไม่มีปัญหา ในบล็อกโพสต์นี้ เราจะสำรวจปัญหาในการอ่านการตอบสนองแบบ chunked
และนำเสนอโซลูชันที่ชัดเจนสำหรับปัญหารทั่วไปนี้
ทำความเข้าใจกับปัญหา
เรามาเริ่มด้วยการสรุปประเด็นหลักกันก่อน พิจารณาสถานการณ์ต่อไปนี้: คุณกำลังใช้ HttpWebResponse
เพื่อดึงข้อมูลจากเซิร์ฟเวอร์เว็บ โค้ดของคุณดูประมาณนี้:
// response เป็น HttpWebResponse
StreamReader reader = new StreamReader(response.GetResponseStream());
string output = reader.ReadToEnd(); // เกิดข้อผิดพลาด...
เมื่อต้องดำเนินการ โค้ดนี้อาจเกิดข้อผิดพลาด IOException
พร้อมข้อความระบุว่า “Unable to read data from the transport connection: The connection was closed.” ข้อผิดพลาดนี้อาจทำให้เกิดความสับสนโดยเฉพาะเมื่อมันไม่ได้เกิดขึ้นเมื่อเซิร์ฟเวอร์ส่งคืนการตอบสนองแบบ non-chunked
ทำไมสิ่งนี้ถึงเกิดขึ้น?
ต้นตอของปัญหาอยู่ที่วิธีที่การถ่ายโอนแบบ chunked
ทำงานภายในโปรโตคอล HTTP เมื่อเซิร์ฟเวอร์ใช้การเข้ารหัสการถ่ายโอนแบบ chunked มันจะส่งข้อมูลในส่วนที่เป็นชิ้น (หรือ chunks) แทนที่จะส่งในหนึ่งการตอบสนองเต็มรูปแบบ เมื่อการเชื่อมต่อถูกปิดเร็วกว่ากำหนด (เช่น หากสตรีมยังอ่านไม่ครบถ้วน) StreamReader
อาจโยนข้อยกเว้น
โซลูชันที่มีประสิทธิภาพ
โชคดีที่มีวิธีการอ่านการตอบสนองแบบ chunked
โดยไม่เกิดปัญหา นี่คือคู่มือทีละขั้นตอนในการอ่านการตอบสนองแบบ chunked อย่างมีประสิทธิภาพใน C#:
1. การใช้บัฟเฟอร์และ StringBuilder
แทนที่จะพึ่งพา StreamReader
เพียงอย่างเดียว คุณสามารถอ่านข้อมูลในส่วนที่เล็กกว่าซึ่งจัดการได้ นี่คือวิธีการที่คุณจะทำได้ด้วยบัฟเฟอร์แบบไบต์และ StringBuilder
:
StringBuilder sb = new StringBuilder();
Byte[] buf = new byte[8192];
Stream resStream = response.GetResponseStream();
string tmpString = null;
int count = 0;
do
{
count = resStream.Read(buf, 0, buf.Length);
if (count != 0)
{
tmpString = Encoding.ASCII.GetString(buf, 0, count);
sb.Append(tmpString);
}
} while (count > 0);
2. คำอธิบายโค้ด
- บัฟเฟอร์แบบไบต์: เราจัดสรรบัฟเฟอร์ที่มีขนาด 8192 ไบต์ นี่หมายความว่าเราจะอ่านการตอบสนองในส่วนของข้อมูลสูงสุดถึง 8 KB ในแต่ละครั้ง
- ลูปการอ่าน: เราอ่านจากสตรีมการตอบสนองอย่างต่อเนื่องจนกว่าจะไม่มีข้อมูลเพิ่มเติม วิธีการ
Read
จะคืนค่าจำนวนไบต์ที่อ่าน ซึ่งเราจะใช้ในการตัดสินใจว่าเราควรดำเนินการต่อในลูปหรือไม่ - StringBuilder สำหรับการสะสมข้อมูล:
StringBuilder
ถูกใช้เพื่อสะสมสตริงที่อ่านมาอย่างมีประสิทธิภาพเพราะมันช่วยลดการใช้หน่วยความจำและอนุญาตให้มีการเติบโตแบบพลศาสตร์
3. การจัดการข้อยกเว้น
สุดท้ายนี้ เป็นสิ่งสำคัญที่จะต้องทราบว่าคุณอาจพบข้อยกเว้นในการดำเนินการ Read()
สุดท้าย ตามที่ผู้ใช้คนหนึ่งแนะนำ คุณสามารถห่อหุ้มส่วนนี้ไว้ในบล็อก try-catch
เพื่อจัดการกับข้อยกเว้นที่เกิดขึ้นอย่างสง่างามโดยไม่ทำให้แอปพลิเคชันของคุณหยุดทำงาน
try
{
// [โค้ดลูปการอ่านที่นี่]
}
catch (IOException ex)
{
// จัดการกับข้อยกเว้นเช่นบันทึกข้อมูลหรือเพิกเฉย
}
สรุป
การอ่านการตอบสนองแบบ chunked
ไม่จำเป็นต้องเป็นประสบการณ์ที่น่าหงุดหงิด โดยการใช้บัฟเฟอร์ไบต์ในการอ่านข้อมูลทีละนิด เราสามารถจัดการการตอบสนองเหล่านี้ได้อย่างมีประสิทธิภาพและมั่นใจว่าเราจัดการกับข้อยกเว้นที่อาจเกิดขึ้นระหว่างการอ่านขั้นสุดท้าย วิธีการนี้ช่วยปรับปรุงความเชื่อถือได้และหลีกเลี่ยงอุปสรรคที่เกี่ยวข้องกับการใช้ StreamReader
โดยตรงกับข้อมูลแบบ chunked
โดยการทำความเข้าใจเทคโนโลยีที่อยู่เบื้องหลังและการใช้กลยุทธ์ที่ถูกต้อง คุณสามารถส่งผ่านความท้าทายกับ HttpWebResponse
ใน C# ได้สำเร็จ
อย่าลังเลที่จะทดลองใช้โซลูชันที่ให้ไว้เพื่อปรับปรุงแอปพลิเคชันของคุณและเร่งการจัดการการตอบสนอง HTTP ของคุณ!