成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

騰訊后端 C++一面:recv 返回值,什么錯(cuò)誤是可接受的?

開發(fā)
在 C/C++網(wǎng)絡(luò)編程中,尤其是在處理 TCP 套接字時(shí),recv函數(shù)扮演著基石般的角色。它是從連接對(duì)端讀取傳入數(shù)據(jù)的主要機(jī)制。

在 C/C++網(wǎng)絡(luò)編程中,尤其是在處理 TCP 套接字時(shí),recv函數(shù)扮演著基石般的角色。它是從連接對(duì)端讀取傳入數(shù)據(jù)的主要機(jī)制。

1. recv 函數(shù)原型

我們先從標(biāo)準(zhǔn)的 POSIX 函數(shù)原型開始:

#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • sockfd: 接收數(shù)據(jù)的套接字文件描述符。
  • buf: 指向用于存儲(chǔ)接收數(shù)據(jù)的緩沖區(qū)的指針。
  • len: buf緩沖區(qū)的最大長(zhǎng)度,即本次調(diào)用最多接收的字節(jié)數(shù)。
  • flags: 控制接收操作的標(biāo)志位(例如 MSG_PEEK, MSG_WAITALL)。通常設(shè)為 0 表示標(biāo)準(zhǔn)行為。

返回值 ssize_t 類型對(duì)于理解調(diào)用的結(jié)果至關(guān)重要。

2. 解讀 recv 返回值

recv 函數(shù)的返回值主要有以下三種情況:

(1) 返回值 > 0: 成功接收數(shù)據(jù)

  • 含義: 調(diào)用成功,并從對(duì)端接收到了數(shù)據(jù)。 
  • 值: 返回值表示實(shí)際接收到并放入buf中的字節(jié)數(shù)。 
  • 注意: 這個(gè)值可能小于你請(qǐng)求的 len,即使發(fā)送方發(fā)送了更多的數(shù)據(jù)。這是正?,F(xiàn)象,原因包括網(wǎng)絡(luò)緩沖區(qū)大小、TCP 分段、以及調(diào)用時(shí)套接字接收緩沖區(qū)中實(shí)際可用的數(shù)據(jù)量等。
  • 處理: 處理接收到的 返回值 這么多字節(jié)的數(shù)據(jù)。如果你的應(yīng)用層協(xié)議期望更多的數(shù)據(jù),你可能需要在一個(gè)循環(huán)中再次調(diào)用 recv,直到接收到完整的消息或發(fā)生錯(cuò)誤/連接關(guān)閉。

(2) 返回值 == 0: 對(duì)端已正常關(guān)閉連接

  • 含義: 遠(yuǎn)端對(duì)等方(peer)已經(jīng)執(zhí)行了有序關(guān)閉序列(發(fā)送了 FIN 包),表示它不會(huì)再發(fā)送任何數(shù)據(jù)了。
  • 值: 0。 
  • 注意: 這不是一個(gè)錯(cuò)誤。這是一個(gè)信號(hào),表明連接的讀取方向已經(jīng)由對(duì)端關(guān)閉。你無(wú)法再?gòu)拇诉B接接收到任何數(shù)據(jù)。
  • 處理: 識(shí)別到連接正在關(guān)閉。通常應(yīng)停止嘗試接收數(shù)據(jù),可能需要關(guān)閉你自己的寫端(如果還沒(méi)關(guān)閉,使用 shutdown(sockfd, SHUT_WR)),并最終調(diào)用 close(sockfd) 來(lái)釋放套接字資源。

(33) 返回值 == -1: 發(fā)生錯(cuò)誤

  • 含義: recv 調(diào)用失敗。 
  • 值: -1。
  • 處理: 這是錯(cuò)誤處理的關(guān)鍵所在,不同的值處理方式是不一樣的。

錯(cuò)誤處理:哪些 errno 值是“可接受”的?

當(dāng) recv 返回 -1 時(shí),并非所有的 errno 值都意味著連接已死或必須立即放棄。有些錯(cuò)誤指示的是臨時(shí)狀態(tài)或需要特定處理邏輯的情況,而不是直接終止連接。這些就是在面試題里面說(shuō)的“可接受”的錯(cuò)誤。

(1) “可接受” / 非致命錯(cuò)誤

① EAGAIN 或 EWOULDBLOCK: (這兩個(gè)宏通常具有相同的值)

  • 場(chǎng)景: 主要發(fā)生在套接字被設(shè)置為非阻塞模式 (O_NONBLOCK) 時(shí)。
  • 含義: 當(dāng)前套接字的接收緩沖區(qū)中沒(méi)有數(shù)據(jù)可讀,并且在不阻塞的情況下無(wú)法立即完成讀取操作。這不是一個(gè)真正的錯(cuò)誤,而是對(duì)套接字狀態(tài)的一種描述。
  • 處理: 不要關(guān)閉連接。這是非阻塞 I/O 中的預(yù)期行為。標(biāo)準(zhǔn)的處理方式是使用 I/O 多路復(fù)用機(jī)制(如 epoll, select, poll)。這些機(jī)制會(huì)通知你套接字何時(shí)變?yōu)榭勺x狀態(tài),屆時(shí)你再安全地重試 recv 調(diào)用。在一個(gè)緊密循環(huán)中反復(fù)調(diào)用 recv 而不等待(忙等待)是非常低效的。
// 概念性的非阻塞循環(huán)(結(jié)合epoll/select)
while (true) {
    // 使用epoll_wait, select等等待sockfd變?yōu)榭勺x
    // ... 等待邏輯 ...

    ssize_tbytes_received= recv(sockfd, buffer, sizeof(buffer), 0);

    if (bytes_received > 0) {
        // 處理數(shù)據(jù)...
    } elseif (bytes_received == 0) {
        // 對(duì)端關(guān)閉連接
        handle_close(sockfd);
        break;
    } else { // bytes_received == -1
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // 當(dāng)前無(wú)數(shù)據(jù)可用,返回繼續(xù)等待(epoll/select)
            continue;
        } elseif (errno == EINTR) {
            // 被信號(hào)中斷,直接重試
            continue;
        } else {
            // 發(fā)生其他錯(cuò)誤
            perror("recv failed"); // 打印錯(cuò)誤信息
            handle_error_close(sockfd); // 處理錯(cuò)誤并關(guān)閉連接
            break;
        }
    }
}

② EINTR:

  • 含義:recv系統(tǒng)調(diào)用被一個(gè)應(yīng)用程序捕獲到的信號(hào)(signal)所中斷,并且中斷發(fā)生在任何數(shù)據(jù)傳輸完成之前。
  • 處理:這通常被認(rèn)為是一個(gè)暫時(shí)的中斷。操作并未完成,但這并不一定意味著套接字本身有問(wèn)題。標(biāo)準(zhǔn)的做法是簡(jiǎn)單地在循環(huán)中立即重試 recv調(diào)用。

(2) 致命 / 不可恢復(fù)錯(cuò)誤

這些錯(cuò)誤通常表明連接本身、套接字狀態(tài)或程序邏輯存在問(wèn)題。在這些錯(cuò)誤發(fā)生后繼續(xù)在該套接字上操作通常是無(wú)意義或不可能的。

  • ECONNRESET: 連接被對(duì)端重置。對(duì)方發(fā)送了 RST(重置)包,很可能是因?yàn)閷?duì)方異常終止或網(wǎng)絡(luò)問(wèn)題。連接已失效。
  • ENOTCONN: 套接字未連接(例如,在 TCP 套接字上調(diào)用 connect 或 accept 之前,或連接已斷開后嘗試 recv)。
  • ETIMEDOUT: 連接超時(shí)??赡茉谶B接建立階段發(fā)生,或在數(shù)據(jù)傳輸過(guò)程中由于網(wǎng)絡(luò)狀況極差或設(shè)置了 SO_RCVTIMEO 并發(fā)生較長(zhǎng)超時(shí)而發(fā)生。通常意味著連接不可用。
  • ECONNREFUSED: 遠(yuǎn)程主機(jī)主動(dòng)拒絕連接(更常見(jiàn)于 connect 調(diào)用,但在特定的 UDP recvfrom 場(chǎng)景下也可能遇到)。
  • EBADF: 無(wú)效的文件描述符 (sockfd 沒(méi)有指向一個(gè)打開的套接字)。這是程序邏輯錯(cuò)誤。
  • EFAULT: 傳入的緩沖區(qū)指針 buf 指向了進(jìn)程地址空間之外的無(wú)效內(nèi)存。這是程序邏輯錯(cuò)誤。
  • EINVAL: 提供了無(wú)效的參數(shù)(例如,無(wú)效的 flags)。程序邏輯錯(cuò)誤。
  • ENOTSOCK: 文件描述符 sockfd 指的不是一個(gè)套接字。程序邏輯錯(cuò)誤。

對(duì)于致命錯(cuò)誤的處理: 記錄具體的 errno 值和錯(cuò)誤信息(使用 perror 或 strerror),清理與該連接相關(guān)的資源,并調(diào)用 close(sockfd) 關(guān)閉套接字。

回答

  • 區(qū)分出 recv 的三種返回值 (>0, 0, -1) 及其含義。
  • 知道 -1 需要檢查 errno。
  • 明確指出 EAGAIN/EWOULDBLOCK 和 EINTR 是可接受的、需要特殊處理(等待/重試)的錯(cuò)誤,尤其是在非阻塞 I/O 場(chǎng)景下 EAGAIN/EWOULDBLOCK 是正常情況。

對(duì)于“什么錯(cuò)誤是可接受的?”這個(gè)問(wèn)題,最核心的答案是 EAGAIN (或 EWOULDBLOCK) 和 EINTR。

責(zé)任編輯:趙寧寧 來(lái)源: CppPlayer
相關(guān)推薦

2025-06-16 03:22:00

2024-01-24 11:35:28

C++多返回值開發(fā)

2024-06-06 09:03:37

MySQL數(shù)據(jù)庫(kù)共享鎖

2025-05-27 10:15:00

void*函數(shù)開發(fā)

2021-08-13 11:31:23

HTTP

2021-08-04 12:11:40

GitHub開發(fā)社區(qū)FSF

2024-09-27 16:33:44

2022-07-26 07:51:40

ThreadRunnableFuture

2024-10-22 15:25:20

2025-04-15 10:00:00

Feign負(fù)載均衡微服務(wù)

2022-05-11 22:15:51

云計(jì)算云平臺(tái)

2025-03-20 09:59:55

Spring@ProfileJava

2009-09-07 03:07:11

C# Main方法

2009-07-30 14:38:36

云計(jì)算

2020-09-19 17:46:20

React Hooks開發(fā)函數(shù)

2022-04-12 11:38:06

C語(yǔ)言全局變量

2022-01-17 06:58:35

C語(yǔ)言函數(shù)錯(cuò)誤碼

2025-03-24 07:35:00

開發(fā)注解Spring

2024-11-26 08:52:34

SQL優(yōu)化Kafka

2011-12-22 20:53:40

Android
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 五月婷婷丁香 | 国产精品免费视频一区 | 狠狠色综合网站久久久久久久 | 免费视频二区 | 亚洲精品视频免费 | 亚洲一区在线日韩在线深爱 | 久久精品99国产精品 | 国产亚洲精品精品国产亚洲综合 | 成年人在线观看视频 | 久久婷婷香蕉热狠狠综合 | 一级毛片在线播放 | 国产一区二区三区精品久久久 | 欧美视频一区二区三区 | 久久极品| 一级毛片成人免费看a | 亚洲精品在线看 | 岛国av一区二区 | 极品销魂美女一区二区 | 九九久久这里只有精品 | 欧美视频1 | 一级欧美视频 | 久久99久久 | 97精品国产 | 亚洲精品一区二区冲田杏梨 | 国产99久久久国产精品下药 | 久久久久久久久久久爱 | 日韩在线观看一区二区三区 | 四虎在线播放 | 亚洲欧美日本在线 | 欧美一级片中文字幕 | 午夜男人免费视频 | 99精品亚洲国产精品久久不卡 | 国产99久久精品一区二区永久免费 | 国外成人免费视频 | 天天操夜夜爽 | 超碰在线免费av | 欧美成人a∨高清免费观看 欧美日韩中 | 亚洲一区二区电影网 | 久久久久久久国产精品影院 | 久久久久久一区 | 岛国视频 |