亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C/C++ Socket設置接收超時時間的多種方法

 更新時間:2024年01月24日 10:29:56   作者:Dontla  
網(wǎng)絡編程中經(jīng)常需要處理的一個問題就是如何正確地處理Socket超時,對于C/C++,有幾種常用的技術可以用來設置Socket接收超時時間,在這篇文章中,我們將詳細介紹如何在C/C++中設置Socket的非阻塞模式以及如何配置接收超時時間,需要的朋友可以參考下

C/C++ Socket設置非阻塞模式接收超時時間的多種方法

網(wǎng)絡編程中經(jīng)常需要處理的一個問題就是如何正確地處理Socket超時。對于C/C++,有幾種常用的技術可以用來設置Socket接收超時時間。在這篇文章中,我們將詳細介紹如何在C/C++中設置Socket的非阻塞模式以及如何配置接收超時時間。

非阻塞模式(fcntl)

默認情況下,Socket操作都是阻塞的。這意味著當調用某個Socket函數(shù)時(例如recv),如果數(shù)據(jù)還未就緒,函數(shù)會阻塞等待,直到有數(shù)據(jù)可用為止。然而,在許多情況下,讓函數(shù)阻塞并不是最佳解決方案(容易造成卡死)。這時,就需要使用非阻塞模式。

設置非阻塞模式

要將Socket設置為非阻塞模式,可以使用fcntl函數(shù)。以下是一段示例代碼:

int flags = fcntl(sock_fd, F_GETFL, 0);
fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);

上述代碼首先獲取了Socket當前的文件狀態(tài)標志,然后將O_NONBLOCK標志位添加到文件狀態(tài)標志中,最后使用F_SETFL命令將新的文件狀態(tài)標志設置回Socket。此時,Socket已經(jīng)處于非阻塞模式。

非阻塞模式下的接收超時

在非阻塞模式下,如果沒有數(shù)據(jù)可用,recv函數(shù)會立即返回一個錯誤,并設置errno為EWOULDBLOCKEAGAIN。因此,可以通過檢查errno來確定是否超時。以下是一段示例代碼:

#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#define MAX_RETRIES 5
#define SLEEP_DURATION 1000000 // One second
#define BUFFER_SIZE 1024

int retries = 0;
char buffer[BUFFER_SIZE];

while(retries < MAX_RETRIES) {
    memset(buffer, 0, sizeof(buffer)); // Clear the buffer
    ssize_t recv_status = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0);

    if(recv_status < 0) {
        if(errno == EWOULDBLOCK || errno == EAGAIN) {
            usleep(SLEEP_DURATION);
            retries++;
        } else {
            perror("Error in recv"); // Print error message
            break;
        }
    } else if(recv_status == 0) { // Socket is closed
        printf("Socket is closed by the peer\n");
        break;
    } else { 
        // Handle received data
        printf("Received data: %s\n", buffer);
        break;
    }
}

if(retries >= MAX_RETRIES) {
    printf("Failed to receive data after %d retries\n", MAX_RETRIES);
}

在上述代碼中,我們在一個循環(huán)中不斷地嘗試接收數(shù)據(jù)。如果recv返回了錯誤,并且errno被設置為EWOULDBLOCK或EAGAIN,我們就讓進程睡眠一段時間,然后重試。如果嘗試了指定的次數(shù)還未能成功接收到數(shù)據(jù),那么我們就認為已經(jīng)超時。

這種方法的優(yōu)點是簡單直觀。但缺點是可能會占用大量的CPU資源,因為在超時期間,程序會不斷地在循環(huán)中運行。

使用select函數(shù)

另一種處理Socket超時的方法是使用select函數(shù)。select函數(shù)可以監(jiān)聽一組文件描述符,等待它們中的任何一個進入就緒狀態(tài)(例如,數(shù)據(jù)可讀),或者直到超時。這種方法的優(yōu)點是可以同時監(jiān)聽多個Socket,并且不會占用過多的CPU資源。

使用select設置接收超時

以下是一段使用select設置接收超時的示例代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define TIMEOUT_SECONDS 5
#define BUFFER_SIZE 1024

int main() {
    fd_set set;
    struct timeval timeout;
    char buffer[BUFFER_SIZE];
    int sock_fd;

    // TODO: Initialize the socket here. You need to write your own logic to do this.

    FD_ZERO(&set);
    FD_SET(sock_fd, &set);

    timeout.tv_sec = TIMEOUT_SECONDS;
    timeout.tv_usec = 0;

    int rv = select(sock_fd + 1, &set, NULL, NULL, &timeout);
    if(rv == 0) {
        // Timeout
        printf("Timeout occurred! No data after %d seconds.\n", TIMEOUT_SECONDS);
    } else if(rv < 0) {
        // Error occurred
        perror("Error occurred in select");
    } else {
        // Socket ready, can receive data now
        ssize_t bytes_received = recv(sock_fd, buffer, BUFFER_SIZE - 1, 0); // leave space for '\0'
        if(bytes_received < 0) {
            // Error occurred in recv
            perror("Error occurred in recv");
        } else {
            // Null-terminate the received data
            buffer[bytes_received] = '\0';
            printf("Received data: %s\n", buffer);
        }
    }

    // Clean up and close the socket
    if(close(sock_fd) < 0) {
        perror("Error occurred while closing the socket");
    }

    return 0;
}

在上述代碼中,我們首先初始化了一個文件描述符集合和一個時間間隔結構體。然后,我們將目標Socket添加到文件描述符集合中,并設置了超時時間。最后,我們調用select函數(shù)并檢查其返回值。如果select返回0,表示已經(jīng)超時。如果select返回負數(shù),表示發(fā)生了錯誤。如果select返回正數(shù),表示有文件描述符已經(jīng)就緒,此時我們就可以調用recv來接收數(shù)據(jù)了。

setsockopt方法設置Socket超時

除了上述介紹的非阻塞模式和select函數(shù),還有一種常用的方法是使用setsockopt函數(shù)來直接設置Socket的超時時間。

setsockopt函數(shù)概述

setsockopt函數(shù)用于設置指定的Socket選項。它的原型如下:

int setsockopt(int sockfd, int level, int optname,
               const void *optval, socklen_t optlen);

這個函數(shù)接收五個參數(shù):sockfd是要設置的Socket的文件描述符;level指定選項所在的協(xié)議層;optname是需要設置的選項的名稱;optval指向包含新選項值的緩沖區(qū);optlenoptval緩沖區(qū)的大小。

使用setsockopt設置接收超時

在Socket編程中,SO_RCVTIMEOSO_SNDTIMEO選項可以分別用來設置接收和發(fā)送超時。這兩個選項都位于套接字層,所以在調用setsockopt函數(shù)時,level參數(shù)應設為SOL_SOCKET。

以下是一段示例代碼,展示如何使用setsockopt設置接收超時:

struct timeval timeout;
timeout.tv_sec = TIMEOUT_SECONDS;
timeout.tv_usec = 0;

if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
    // Error occurred
}

在上述代碼中,我們首先創(chuàng)建了一個timeval結構體,并設置了超時時間。然后,我們調用setsockopt函數(shù),將SO_RCVTIMEO選項的值設置為指向timeout結構體的指針。如果setsockopt返回負數(shù),表示發(fā)生了錯誤。

需要注意的是,SO_RCVTIMEO和SO_SNDTIMEO選項設置的超時時間是一個總時間,而不是在Socket函數(shù)阻塞時每次等待的時間。這意味著,如果你在一個循環(huán)中多次調用recv函數(shù),那么這些函數(shù)調用的總時間將不會超過你設置的超時時間。

完整示例代碼

下面是一個unix domain socket使用setsockopt函數(shù)設置接收超時的示例代碼(用文件套接字通信),其中FILE_PATH是文件路徑。

bool nonBlockingRecv()
{
    struct sockaddr_un addr;
    int sock_fd;
    char buffer[BUFFER_SIZE] = "REQ";
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, FILE_PATH.c_str());
    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock_fd < 0)
    {
        std::cout << "Request socket failed\n";
        return false;
    }

    if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        std::cout << "Connect socket failed\n";
        close(sock_fd);
        return false;
    }

    //1.send command
    SEND_INFO(COMMAND);

    // Set recv timeout to 100ms
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000; // 100 ms
    if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) 
    {
        std::cout << "Setting socket timeout failed\n";
        close(sock_fd);
        return false;
    }

    //2.receive response of register req
    memset(buffer, 0, BUFFER_SIZE);
    int recv_status = recv(sock_fd, buffer, BUFFER_SIZE, 0);
    if (recv_status < 0) 
    {
        if (errno == EWOULDBLOCK || errno == EAGAIN) 
        {
            std::cout << "Receive timeout\n";
        } 
        else 
        {
            std::cout << "Receive error\n";
        }
        close(sock_fd);
        return false;
    }

    std::cout << "Received [" << buffer << "] from manager" << std::endl;

    //3.check result
    if (NULL != strstr(buffer, SUCCESS.c_str()))//receive success.
    {
        std::cout << "Received success\n";
        close(sock_fd);
        return true;
    }
    else
    {
        std::cout << "Received fail\n";
        close(sock_fd);
        return false;
    }
}

小結

使用setsockopt函數(shù)設置SO_RCVTIMEO選項是一種直接且有效的方法來設置Socket接收超時。這種方法的優(yōu)點是簡單直觀,只需要一行代碼就可以完成設置。然而,它的缺點是靈活性較差,因為它只能設置一個固定的超時時間,而不能動態(tài)地根據(jù)網(wǎng)絡狀況調整超時時間。

總結

在C/C++中,有多種方法可以用來設置Socket接收超時時間。非阻塞模式和select函數(shù)亦或setsockopt函數(shù)都是處理這個問題的有效工具。需要注意的是,選擇哪種方法取決于具體的應用場景。例如,如果你需要同時處理多個Socket,那么select函數(shù)可能是更好的選擇。如果想要方便,setsockopt函數(shù)可以考慮

以上就是C/C++ Socket設置接收超時時間的多種方法的詳細內容,更多關于C/C++ Socket接收超時時間的資料請關注腳本之家其它相關文章!

相關文章

  • 基于稀疏圖上的Johnson算法的詳解

    基于稀疏圖上的Johnson算法的詳解

    本篇文章介紹了,稀疏圖上的Johnson算法的詳解。需要的朋友參考下
    2013-05-05
  • Qt數(shù)據(jù)庫應用之實現(xiàn)數(shù)據(jù)打印到紙張

    Qt數(shù)據(jù)庫應用之實現(xiàn)數(shù)據(jù)打印到紙張

    關于Qt打印內容到紙張,網(wǎng)上的辦法非常多,比如有些直接用painter繪制,逐步控制分頁打印。本文介紹的方法則是將內容作為html設置到文檔對象,再調用文檔對象的print方法傳入QPrinter對象打印,感興趣的同學可以了解一下
    2022-01-01
  • C++ XML庫用法詳解

    C++ XML庫用法詳解

    TinyXML-2是C++中一個輕量級、易于使用的XML解析庫,支持XML的讀取和寫入,內存占用小,適合嵌入式系統(tǒng),本文給大家介紹C++ XML庫用法,感興趣的朋友一起看看吧
    2025-03-03
  • c語言中main函數(shù)用法及知識點總結

    c語言中main函數(shù)用法及知識點總結

    在本篇文章里小編給大家分享的是一篇關于c語言中main函數(shù)用法及知識點總結內容,有需要的朋友們可以跟著學習參考下。
    2021-10-10
  • c++ vector對象相關總結

    c++ vector對象相關總結

    這篇文章主要介紹了c++ vector對象的相關資料,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下
    2021-02-02
  • 獲取本地網(wǎng)卡適配器信息具體代碼

    獲取本地網(wǎng)卡適配器信息具體代碼

    這篇文章主要介紹了獲取本地網(wǎng)卡適配器信息具體代碼,有需要的朋友可以參考一下
    2013-12-12
  • C++實現(xiàn)俄羅斯方塊源碼

    C++實現(xiàn)俄羅斯方塊源碼

    這篇文章主要為大家詳細介紹了C++實現(xiàn)俄羅斯方塊源碼完整版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++實現(xiàn)順序表的方法

    C++實現(xiàn)順序表的方法

    本文給大家?guī)砹薈++實現(xiàn)順序表的方法,代碼簡單易懂,附有注釋,感興趣的朋友一起看下吧
    2016-08-08
  • Qt消除警告的實現(xiàn)示例

    Qt消除警告的實現(xiàn)示例

    Qt5 和 Qt6 之間存在一些差異,導致在編譯時可能產(chǎn)生警告,為了消除這些警告,Qt 提供了一些宏定義來幫助你在代碼中處理這些差異,本文主要介紹了Qt消除警告的實現(xiàn)示例,感興趣的可以了解一下
    2023-09-09
  • 快速學習C語言中for循環(huán)語句的基本使用方法

    快速學習C語言中for循環(huán)語句的基本使用方法

    這篇文章主要簡單介紹了C語言中for循環(huán)語句的基本使用方法,是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-11-11

最新評論