ฉันจะพยายามอ่านข้อมูลจากซ็อกเก็ตแบบหมดเวลาได้อย่างไร ฉันรู้ว่าเลือกเลือกแบบสำรวจมีฟิลด์หมดเวลา แต่การใช้พวกเขาปิดใช้งาน "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()จะกลับข้อผิดพลาดกับชุดerrnoEINTR
ลินุกซ์
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()เรียกใช้ฟังก์ชันเพื่อให้ทำงานได้อย่างเหมาะสม