原创---tcp udp: send一次发送数据长度大于recv size_t len时,windows、linux下不同返回

本文探讨了UDP和TCP两种不同协议在数据传输过程中的差异。对于UDP而言,当发送数据长度超过接收缓冲区大小时,未被接收的数据将被丢弃;而TCP则会继续接收剩余数据直至全部接收完毕,不会轻易丢弃数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、udp
linux client:send   send data len
linux server:recv   recv data len
当 send len  <= recv len时,recv接受正常;
当 send len  >  recv len时,recv接受 recv data len,也就是说只接收recv buf len个数据,其余数据没有接收;
while循环,发现接下来的recv 居然没有继续接收剩下的数据,而是接收send发来的新的数据,也就是说上一次没有接收的数据,被udp给舍弃了。


在udp broadcast情况下,udp recv也是这样的。




2、tcp
windows client:send   send data len
windows server:recv   recv data len
当 send len  <= recv len时,recv接受正常;
当 send len  >  recv len时,recv接受 recv data len,也就是说只接收recv buf len个数据,其余数据没有接收;
while循环,发现接下来的recv 居然继续接收剩下的数据,直到接受完成。之后,recv才继续send发来的新的数据,也就是说上一次没有接收的数据,没有被tcp舍弃。


<think>好的,我现在需要解释这段C语言代码:ssize_t recv_len = recv(sockfd, recv_buffer, sizeof(recv_buffer), 0);。用户可能对套接字编程太熟悉,所以得一步步来。 首先,回忆一下recv函数的作用。recv用于从已连接的套接字接收数据。那参数呢?sockfd是套接字描述符,recv_buffer是缓冲区,sizeof(recv_buffer)应该是缓冲区大小,最后一个参数是标志位,这里为0,表示默认行为。 接下来,返回类型是ssize_t,这是有符号的整数类型,通常用于表示字节数或者错误。返回值可能为正数表示接收的字节数,0表示连接关闭,负数表示错误。需要提到这些情况。 然后,每个参数的具体含义。sockfd需要是已经建立连接的,比如TCPrecv_buffer是存储数据的内存区域,sizeof计算缓冲区大小,防止溢出。标志位0可能阻塞调用,直到有数据到达。 可能需要注意的地方:缓冲区的大小是否正确,recv_len的处理,比如检查错误需要判断是否小于0,并处理EINTR等错误。如果是非阻塞模式,返回值可能为-1且errno为EAGAIN或EWOULDBLOCK,但这里标志位是0,所以默认是阻塞的。 还要提醒用户,实际接收的数据可能小于缓冲区大小,所以需要根据recv_len来处理有效数据,避免使用未初始化的部分。 有没有可能漏掉什么?比如,recvTCPUDP中的不同表现,但这里代码没指定,所以假设是面向流的TCP。另外,sizeof用在数组上才正确,如果recv_buffer是指针,sizeof会对,需要确认用户是否正确使用。 总结,代码的作用是从套接字接收数据,存储到缓冲区,返回接收的字节数或错误。需要处理各种返回值情况,确保程序健壮性。</think>以下是对代码 `ssize_t recv_len = recv(sockfd, recv_buffer, sizeof(recv_buffer), 0);` 的详细解释: --- ### 1. **函数功能** `recv()` 是用于从**已连接的套接字**接收数据的系统调用,常用于TCP协议(面向连接的通信)。它的核心行为是: - 从套接字 `sockfd` 的接收缓冲区中读取数据-数据存入用户提供的缓冲区 `recv_buffer`。 - 返回实际读取的字节数,或错误信息。 --- ### 2. **参数解析** #### 参数1:`sockfd` - **类型**:`int` - **作用**:已建立的套接字文件描述符(通过 `socket()` 创建,且已完成连接,如 `connect()` 或 `accept()`)。 - **注意**:若套接字未连接,`recv()` 会失败。 #### 参数2:`recv_buffer` - **类型**:`void*`(通常是 `char[]` 或 `char*`) - **作用**:存储接收数据的缓冲区。 - **注意**:需确保缓冲区足够大,避免溢出。`sizeof(recv_buffer)` 可自动计算缓冲区大小(仅当 `recv_buffer` 是数组有效;若为指针,需手动指定长度)。 #### 参数3:`sizeof(recv_buffer)` - **类型**:`size_t` - **作用**:指定缓冲区的最大容量(单位:字节)。 - **注意**:实际接收的数据量可能小于此值。 #### 参数4:`0` - **类型**:`int` - **作用**:标志位(flags),控制接收行为。`0` 表示默认阻塞模式: - 若无数据可读,函数会阻塞直到数据到达。 - 其他常见标志如 `MSG_DONTWAIT`(非阻塞)、`MSG_PEEK`(查看数据移除缓冲区)等。 --- ### 3. **返回值** - **类型**:`ssize_t`(有符号整数) - **含义**: - **正数**:实际接收的字节数。 - **0**:对端关闭连接(TCP的FIN报文)。 - **-1**:发生错误,需通过 `errno` 判断具体原因(如 `EINTR` 被信号中断、`ECONNRESET` 连接重置等)。 --- ### 4. **代码执行流程** 1. 调用 `recv()` 尝试从 `sockfd` 读取数据。 2. 数据存入 `recv_buffer`,最大长度为 `sizeof(recv_buffer)`。 3. 返回实际读取的字节数 `recv_len`。 --- ### 5. **典型使用场景** ```c char recv_buffer[1024]; ssize_t recv_len = recv(sockfd, recv_buffer, sizeof(recv_buffer), 0); if (recv_len > 0) { // 成功读取数据,处理 recv_buffer[0..recv_len-1] } else if (recv_len == 0) { // 对端关闭连接 close(sockfd); } else { // 处理错误 perror("recv() failed"); } ``` --- ### 6. **注意事项** - **阻塞非阻塞模式**:若套接字设置为非阻塞(通过 `fcntl()`),`recv()` 可能立即返回 `-1`,并设置 `errno` 为 `EAGAIN` 或 `EWOULDBLOCK`。 - **缓冲区管理**:需根据 `recv_len` 处理有效数据,避免使用未初始化的内存。 - **信号中断**:若 `recv()` 被信号中断(`errno == EINTR`),通常需重试调用。 --- ### 7. **相关函数** - `send()`:向套接字发送数据- `read()`:通用的文件读取函数(可用于套接字,但如 `recv()` 灵活)。 - `recvfrom()`:用于无连接协议(如UDP)。 若有进一步问题(如错误处理、非阻塞模式),可继续提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值