ฉันจะพยายามอ่านข้อมูลจากซ็อกเก็ตแบบหมดเวลาได้อย่างไร ฉันรู้ว่าเลือกเลือกแบบสำรวจมีฟิลด์หมดเวลา แต่การใช้พวกเขาปิดใช้งาน "tcp fast-path" ใน tcp reno stack
ความคิดเดียวที่ฉันมีคือใช้ recv (fd, ... , MSG_DONTWAIT) ในวง
ฉันจะพยายามอ่านข้อมูลจากซ็อกเก็ตแบบหมดเวลาได้อย่างไร ฉันรู้ว่าเลือกเลือกแบบสำรวจมีฟิลด์หมดเวลา แต่การใช้พวกเขาปิดใช้งาน "tcp fast-path" ใน tcp reno stack
ความคิดเดียวที่ฉันมีคือใช้ recv (fd, ... , MSG_DONTWAIT) ในวง
คำตอบ:
คุณสามารถใช้ฟังก์ชันsetsockoptเพื่อกำหนดระยะหมดเวลาของการดำเนินการรับ:
SO_RCVTIMEO
ตั้งค่าการหมดเวลาที่ระบุระยะเวลาสูงสุดที่ฟังก์ชันอินพุตจะรอจนกว่าจะเสร็จสิ้น ยอมรับโครงสร้างเวลาที่มีจำนวนวินาทีและไมโครวินาทีที่ระบุขีด จำกัด ระยะเวลาที่ต้องรอให้การดำเนินการป้อนข้อมูลเสร็จสมบูรณ์ หากการดำเนินการรับถูกบล็อกในช่วงเวลานี้โดยไม่ได้รับข้อมูลเพิ่มเติมการดำเนินการจะกลับมาพร้อมกับการนับบางส่วนหรือตั้งค่าผิดพลาดเป็น [EAGAIN] หรือ [EWOULDBLOCK] หากไม่มีการรับข้อมูล ค่าเริ่มต้นสำหรับตัวเลือกนี้คือศูนย์ซึ่งบ่งชี้ว่าการดำเนินการรับจะไม่หมดเวลา ตัวเลือกนี้ใช้โครงสร้างเวลา โปรดทราบว่าการใช้งานบางอย่างไม่อนุญาตให้ตั้งค่าตัวเลือกนี้
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
รายงานบน Windows bind
นี้ควรจะทำก่อนที่จะเรียก ฉันได้ตรวจสอบโดยการทดลองแล้วว่าสามารถทำได้ก่อนหรือหลังbind
บน Linux และ OS X
struct timeval tv;
หมายความว่า select () จะไม่ทำงานด้วยหรือเปล่า? ฉันลองย้ายรหัส select () ไปที่ windows แล้วมันก็หมดเวลาทันทีดูเหมือนว่ามันจะไม่สนใจค่าที่ฉันตั้งไว้ในช่วงเวลา
นี่คือรหัสง่ายๆในการเพิ่มเวลานอกให้กับrecv
ฟังก์ชันของคุณโดยใช้poll
ใน C:
struct pollfd fd;
int ret;
fd.fd = mySocket; // your socket handler
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
case -1:
// Error
break;
case 0:
// Timeout
break;
default:
recv(mySocket,buf,sizeof(buf), 0); // get your data
break;
}
poll
จะรอรับอย่างน้อยหนึ่งไบต์หรือหมดเวลาในขณะที่เมื่อเรียกใช้recv
ฟังก์ชันจะรอเป็นsizeof(buf)
ไบต์ทำให้บล็อกอีกครั้งหากยังไม่ถึงจำนวนนี้ แต่เวลานี้ไม่มีการหมดเวลา
// ใช้งานได้หลังจากการดำเนินการผูกสำหรับ WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
ติดตั้งจัดการหาSIGALRM
แล้วใช้alarm()
หรือก่อนที่จะปิดกั้นปกติualarm()
recv()
หากปลุกไปปิดที่recv()
จะกลับข้อผิดพลาดกับชุดerrno
EINTR
ลินุกซ์
struct timeval tv;
tv.tv_sec = 30; // 30 Secs Timeout
tv.tv_usec = 0; // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
WINDOWS
DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
หมายเหตุ : คุณได้ตั้งค่านี้ก่อนbind()
เรียกใช้ฟังก์ชันเพื่อให้ทำงานได้อย่างเหมาะสม