C ++ Boost ASIO: จะอ่าน / เขียนด้วยการหมดเวลาได้อย่างไร

จากการอ่านรายการ Stack Overflow อื่นๆ และเอกสารประกอบ boost::asio ฉันยืนยันว่าไม่มีการเรียกการอ่าน/เขียน ASIO แบบซิงโครนัสที่ให้การหมดเวลาใช้งานง่ายเป็นพารามิเตอร์สำหรับการโทร

ฉันกำลังอยู่ระหว่างการแปลงแอปพลิเคชันซ็อกเก็ต Linux รุ่นเก่าด้วยการเรียกแบบเลือก (2) ที่ใช้การหมดเวลา และฉันต้องทำสิ่งเดียวกันไม่มากก็น้อย

ดังนั้นวิธีที่ดีที่สุดในการทำเช่นนี้ใน boost::asio คืออะไร? เมื่อดูเอกสารประกอบของ asio มีตัวอย่างที่น่าสับสนมากมายเกี่ยวกับสิ่งต่าง ๆ ที่เกี่ยวข้องกับตัวจับเวลา แต่ฉันค่อนข้างสับสน

ฉันอยากเห็นตัวอย่างที่อ่านง่ายของสิ่งนี้: อ่านจากซ็อกเก็ต แต่รอสูงสุด X วินาทีหลังจากนั้นฟังก์ชันจะส่งคืนโดยไม่มีสิ่งใดเลย หรือส่งคืนพร้อมกับอะไรก็ตามที่อ่านได้ จากซ็อกเก็ตก่อนที่การหมดเวลาจะหมดลง


person Stéphane    schedule 29.12.2010    source แหล่งที่มา
comment
คุณช่วยอธิบายรายละเอียดสิ่งที่ทำให้เกิดความสับสนเกี่ยวกับตัวอย่างนี้ได้ไหม: think-async.com/Asio/asio-1.4.7/src/examples/timeouts/ - ตรรกะที่สำคัญคือคุณส่งงานอะซิงก์ 2 งาน งานหนึ่งเป็นการอ่าน/เขียน และอีกงานหนึ่งเป็นการหมดเวลาหาก การอ่าน/เขียนจะส่งกลับก่อนอื่น คุณจะต้องฆ่าตัวจับเวลากำหนดเวลา หากตัวจับเวลากำหนดเวลาส่งคืนตรรกะคือการอ่าน/เขียนยังคงค้างอยู่ - จากนั้นคุณดำเนินการตามตรรกะการหมดเวลาของคุณ ง่ายมาก   -  person    schedule 29.12.2010
comment
มีกรณีมุมหนึ่งที่อาจเกิดขึ้นในเครือข่าย hf ที่เกี่ยวข้องกับการเข้าคิวของการโทรกลับ cb หมดเวลาถูกเข้าคิว จากนั้นการอ่าน/เขียนจะถูกเข้าคิว คุณพบการหมดเวลา cb และเริ่มดำเนินการตรรกะการหมดเวลาเมื่อในความเป็นจริงการอ่าน/เขียนเสร็จสิ้นแล้ว วิธีแก้ไขที่เป็นไปได้ที่ฉันเคยเห็นคือสิ่งที่คล้ายกับการล็อคการตรวจสอบซ้ำ - พูดง่ายๆ ก็คือทำการหมดเวลารองเมื่อการหมดเวลาครั้งแรกกลับมา แต่นี่ก็มีปัญหาเดียวกันจะเกิดอะไรขึ้นถ้าการอ่าน/เขียนถูกเข้าคิวหลังจากการหมดเวลาครั้งที่ 2 คือคิว...   -  person    schedule 29.12.2010
comment
เพียงจำไว้ว่าการหมดเวลานั้นเป็นเงื่อนไขที่ยาก คุณกำลังบอกว่าถ้าฉันไม่ได้รับบางสิ่งบางอย่างในระยะเวลาหนึ่ง ฉันจะทำบางอย่างที่เฉพาะเจาะจง ซึ่งรวมถึงข้อเท็จจริงที่ว่าการอ่าน/เขียนอาจเกิดขึ้นแล้วและกำลังดำเนินการอยู่ สำหรับคุณนั่นไม่ได้เปลี่ยนความจริงที่ว่าคุณยังไม่ได้รับมันในตอนนี้   -  person    schedule 29.12.2010
comment
@zenikoder ฉันเชื่อว่าความสับสนคือโครงสร้างการหมดเวลาจัดทำโดย asio บังคับใช้โดยใช้วิธีอะซิงโครนัส แต่ไม่สามารถใช้กับวิธีซิงโครนัสได้   -  person Sam Miller    schedule 29.12.2010
comment
@Sam: คุณสามารถสร้างการหมดเวลาแบบซิงโครนัส คุณเพียงแค่ซ่อนการเรียกแบบ asynch ไว้ด้านหลังอินเทอร์เฟซแบบซิงโครนัสที่บล็อก จนกว่าจะเกิดการหมดเวลาหรือการอ่าน/เขียน   -  person    schedule 29.12.2010


คำตอบ (2)


สิ่งนี้ถูกนำมาแสดงในรายชื่อผู้รับจดหมายของ asio มี ตั๋ว ที่ร้องขอคุณสมบัติ เช่นกัน. โดยสรุป แนะนำให้ใช้วิธีอะซิงโครนัสหากคุณต้องการหมดเวลาและยกเลิกได้


หากคุณไม่สามารถแปลงเป็นวิธีอะซิงโครนัสได้ คุณอาจลองใช้ตัวเลือกซ็อกเก็ต SO_RCVTIMEO และ SO_SNDTIMEO สามารถตั้งค่าได้ด้วย setsockopt สามารถรับคำอธิบายได้ด้วย boost::asio::ip::tcp::socket::native วิธีการ หน้า man 7 socket man บอกว่า

SO_RCVTIMEO และ SO_SNDTIMEO ระบุการรับหรือการส่งหมดเวลาจนกว่าจะรายงานข้อผิดพลาด อาร์กิวเมนต์คือระยะเวลาของโครงสร้าง หากฟังก์ชันอินพุตหรือเอาต์พุตบล็อกในช่วงเวลานี้ และมีการส่งหรือรับข้อมูล ค่าที่ส่งคืนของฟังก์ชันนั้นจะเป็นจำนวนข้อมูลที่ถ่ายโอน หากไม่มีการถ่ายโอนข้อมูลและถึงการหมดเวลาแล้ว -1 จะถูกส่งกลับโดยตั้งค่า errno เป็น EAGAIN หรือ EWOULDBLOCK เหมือนกับว่าซ็อกเก็ตถูกระบุให้ไม่บล็อก หากการหมดเวลาถูกตั้งค่าเป็นศูนย์ (ค่าเริ่มต้น) การดำเนินการจะไม่มีวันหมดเวลา การหมดเวลามีผลเฉพาะกับการเรียกของระบบที่ทำซ็อกเก็ต I/O (เช่น อ่าน(2), recvmsg(2), ส่ง(2), sendmsg(2)); การหมดเวลาไม่มีผลกับการเลือก (2), โพล (2), epoll_wait (2) ฯลฯ

person Sam Miller    schedule 29.12.2010
comment
คุณอ่านคำตอบของ CH ต่อคำขอหรือไม่ ASIO จำลองการทำงานของระบบปฏิบัติการในภาษา C++ หากคุณต้องการฟังก์ชันการหมดเวลาบางประเภท คุณยินดีเป็นอย่างยิ่งที่จะนำไปใช้งานโดยใช้บิต-n-ชิ้นที่ ASIO มอบให้ - person ; 29.12.2010

ฉันใช้เอกสาร asio บางส่วนเพื่อสร้างสิ่งนี้:

class TimeoutAdjust
{
public:
  TimeoutAdjust(unsigned int dwTimeout) : m_dwTimeout(dwTimeout) {};

  template<class Protocol>
  int level(const Protocol& p) const {return SOL_SOCKET;}

  template<class Protocol>
  int name(const Protocol& p) const {return SO_SNDTIMEO;}

  template<class Protocol>
  const void* data(const Protocol& p) const {return &m_dwTimeout;}

  template<class Protocol>
  size_t size(const Protocol& p) const {return sizeof(m_dwTimeout);}
private:
  unsigned int m_dwTimeout;
};

การใช้งาน:

TimeoutAdjust adjust(5000);
sSocket.set_option(adjust);

ฉันแก้ไขจุดบกพร่องแล้ว และดูเหมือนว่าจะทำสิ่งที่ควรจะเป็น

person ArtHare    schedule 06.07.2013
comment
สิ่งที่ฉันอ่านที่นี่คือ SO_SNDTIMEO รับ timeval แทนที่จะเป็น unsigned int linux.die.net/man/7/socket - person updogliu; 15.07.2014
comment
อ่า เอกสาร MS ใช้ DWORD สำหรับ SO_SNDTIMEO ดูเหมือนว่า timeval จะเป็น int ยาวคู่หนึ่ง ดังนั้นผู้อ่านควรระวัง เอกสาร MS: msdn.microsoft com/en-ca/library/windows/desktop/ - person ArtHare; 15.07.2014
comment
หลังจากใช้โค้ดข้างต้น ฉันได้รับข้อยกเว้น ข้อยกเว้น: set_option: อาร์กิวเมนต์ไม่ถูกต้อง หากคุณมีรหัสอ้างอิงบางส่วน โปรดแบ่งปันรหัสเดียวกันนี้ - person asim; 12.09.2014