ความแตกต่างระหว่างการเชื่อมต่อกับการหมดเวลาอ่านสำหรับซ็อกเก็ตคืออะไร


180

3 คำถาม:

  1. ความแตกต่างระหว่างการเชื่อมต่อและการหมดเวลาอ่านสำหรับซ็อกเก็ตคืออะไร

  2. สิ่งที่ไม่เชื่อมต่อชุดหมดเวลาที่จะ "อินฟินิตี้" หมายความว่าอย่างไร ในสถานการณ์ใดบ้างที่มันจะยังคงอยู่ในวง infinitive? และอะไรที่สามารถกระตุ้นให้วงอินฟินิตี้ตาย?

  3. การหมดเวลาการอ่านที่ตั้งค่าเป็น "อนันต์" หมายถึงอะไร ในสถานการณ์ใดบ้างที่มันจะยังคงอยู่ในวง infinitive? และอะไรที่สามารถกระตุ้นให้วงอินฟินิตี้ตาย?

คำตอบ:


227

1) ความแตกต่างระหว่างการเชื่อมต่อและการหมดเวลาอ่านสำหรับซ็อกเก็ตคืออะไร

การหมดเวลาการเชื่อมต่อคือการหมดเวลาในการเชื่อมต่อเริ่มต้น เช่นเสร็จสิ้นการจับมือการเชื่อมต่อ TCP หมดเวลาการอ่านคือการหมดเวลาในการรอคอยที่จะอ่านข้อมูลที่1 หากเซิร์ฟเวอร์ไม่สามารถส่งไบต์ <timeout> วินาทีหลังจากไบต์สุดท้ายข้อผิดพลาดการหมดเวลาการอ่านจะถูกเพิ่ม

2) การหมดเวลาเชื่อมต่อตั้งค่าเป็น "infinity" หมายความว่าอย่างไร ในสถานการณ์ใดบ้างที่มันจะยังคงอยู่ในวง infinitive? และอะไรที่สามารถกระตุ้นให้วงอินฟินิตี้ตาย?

หมายความว่าความพยายามในการเชื่อมต่อสามารถบล็อกได้ตลอดเวลา ไม่มีการวนซ้ำไม่สิ้นสุด แต่ความพยายามเชื่อมต่อสามารถยกเลิกการบล็อกโดยเธรดอื่นที่ปิดซ็อกเก็ต (การThread.interrupt()โทรอาจทำตามเคล็ดลับ ... ไม่แน่ใจด้วย)

3) การหมดเวลาการอ่านถูกตั้งค่าเป็น "infinity" หมายถึงอะไร ในสถานการณ์ใดที่มันจะสามารถอยู่ในวงวนไม่สิ้นสุดได้? สิ่งที่ทำให้เกิดการวนซ้ำไม่สิ้นสุด

หมายความว่าการเรียกไปreadยังซ็อกเก็ตสตรีมอาจบล็อกตลอดไป อีกครั้งไม่มีลูปไม่มีที่สิ้นสุด แต่readสามารถยกเลิกการปิดกั้นโดยการThread.interrupt()โทรปิดซ็อกเก็ตและ (แน่นอน) ปลายอีกด้านหนึ่งส่งข้อมูลหรือปิดการเชื่อมต่อ


1 - ไม่ใช่ ... อย่างที่ผู้วิจารณ์คนหนึ่งคิดว่า ... การหมดเวลาของซ็อกเก็ตที่สามารถเปิดได้หรือไม่ได้ใช้งาน


8

นี่เป็นค่าการหมดเวลาที่บังคับใช้โดย JVM สำหรับการสร้างการเชื่อมต่อ TCP และรอการอ่านข้อมูลจากซ็อกเก็ต

หากตั้งค่าเป็นอนันต์คุณจะไม่รอตลอดไป มันหมายถึงว่า JVM ไม่มีการหมดเวลาและระบบปฏิบัติการจะเป็นผู้รับผิดชอบในการหมดเวลาทั้งหมด อย่างไรก็ตามหมดเวลาบนระบบปฏิบัติการอาจนานมาก ในบางเครือข่ายที่ช้าฉันเห็นการหมดเวลานานถึง 6 นาที

แม้ว่าคุณจะตั้งค่าการหมดเวลาสำหรับซ็อกเก็ตมันอาจไม่ทำงานหากการหมดเวลาเกิดขึ้นในรหัสเนทีฟ เราสามารถสร้างปัญหาขึ้นอีกครั้งบน Linux โดยเชื่อมต่อกับโฮสต์ที่ถูกบล็อกโดยไฟร์วอลล์หรือถอดสายเคเบิลเมื่อเปิดสวิตช์

วิธีที่ปลอดภัยเพียงวิธีเดียวในการจัดการการหมดเวลา TCP คือการเรียกใช้รหัสการเชื่อมต่อในเธรดอื่นและขัดจังหวะเธรดเมื่อใช้เวลานานเกินไป


"ถ้าตั้งค่าเป็นอินฟินิตี้คุณจะไม่รอตลอดไป" ตราบใดที่มันไม่ได้เกี่ยวกับการอภิปรายเกี่ยวกับความหมายของ "อินฟินิตี้" มันสามารถเกิดขึ้นได้อย่างแน่นอนว่าคุณจะรอนานมาก เรามีกรณีที่นี่ที่HttpURLConnection.getResponseCode()ถูกแขวนสำหรับ apprx หนึ่งสัปดาห์จนกว่าเราจะเริ่มกระบวนการใหม่ เห็นได้ชัดว่าไม่มีการตั้งค่าการหมดเวลาในด้าน JVM และไม่มีการหมดเวลาในด้าน Linux OS
Tom Fink

ย่อหน้าสุดท้ายไม่ถูกต้อง การเชื่อมต่อจะหมดเวลาหลังจากนั้นไม่เกินหนึ่งนาที ไม่จำเป็นต้องมีเธรดแยกต่างหาก แน่นอนคุณสามารถอ่านได้ว่าทำงานตลอดไปหากไม่มีข้อมูล อย่างไรก็ตาม Javadoc นั้นผิดเกี่ยวกับการหมดเวลาเชื่อมต่อเริ่มต้นที่ไม่มีที่สิ้นสุด มันไม่ใช่
มาร์ควิสแห่ง Lorne

1
@comeGetSome นั่นไม่ถูกต้อง คุณสามารถปิดซ็อกเก็ตสำหรับการป้อนข้อมูล ซึ่งจะทำให้การอ่านที่ถูกบล็อกพบจุดสิ้นสุดของสตรีม
มาร์ควิสแห่ง Lorne

@comeGetSome: ฉันต้องใช้สิ่งนี้โดยใช้เธรดที่เก็บการอ้างอิงถึงการเชื่อมต่อ URL HTTP แบบเปิด เมื่อเธรดกล่าวปิดการเชื่อมต่อเธรดอื่นจะพ่น "java.net.SocketException: Socket closed" ขอบคุณข้อผิดพลาด JDK-8075484 ที่ทำให้ฉันทำอย่างนั้น!
fmcato

@comeGetSome แน่นอนคุณสามารถโทรSocket.shutdownInput()โดยไม่ต้องถือมือของคุณหรือไม่ NB หมดเวลาเหล่านี้ถูกบังคับใช้โดย TCP ไม่ใช่ JVM
มาร์ควิสแห่ง Lorne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.