send函数何时返回

send 分阻塞和非阻塞模式的!

  • 1 在阻塞模式下,
    send函数是将应用程序请求发送的数据拷贝到发送缓存中发送并得到接收端的确认后再返回

  • 2 在非阻塞模式下,
    send函数仅仅是将数据拷贝到协议栈的缓存区而已,如果缓存区可用空间不够,则尽能力的拷贝,返回成功拷贝的大小;如缓存区可用空间为0,则返回-1,同时设置errno为EAGAIN.
    但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。

`send()` 函数在以下情况会返回 `-1`,并设置 `errno` 来指示具体错误原因: ### 常见返回 `-1` 的情况(附对应 `errno`) 1. **连接已关闭/重置** - `ECONNRESET`:连接被对端强制重置(如对端进程崩溃) - `ENOTCONN` 或 `EPIPE`:尝试在未建立连接的socket上发送数据 2. **阻塞模式下的超时** - `EAGAIN`/`EWOULDBLOCK`:非阻塞socket发送缓冲区已满(或超时未发送完成) 3. **权限/参数错误** - `EACCES`:无权限发送(如广播地址未设置`SO_BROADCAST`选项) - `EINVAL`:无效参数(如传递了错误的flag) - `ENOTSOCK`:文件描述符不是socket 4. **系统资源问题** - `ENOBUFS`:内核缓冲区不足 - `ENOMEM`:内存不足 5. **网络问题** - `ENETDOWN`:网络接口不可用 - `EHOSTUNREACH`:目标主机不可达 ### 关键行为说明 - **阻塞socket**:会等待直到数据进入发送缓冲区或发生错误 - **非阻塞socket**:立即返回`EAGAIN`/`EWOULDBLOCK`(如果缓冲区满) - **部分发送**:可能返回小于请求长度的正值(需循环发送剩余数据) ### 典型错误处理代码示例 ```c ssize_t ret = send(sockfd, buf, len, flags); if (ret == -1) { switch (errno) { case EAGAIN: // 等同于EWOULDBLOCK // 非阻塞模式下需等待可写事件(用select/poll/epoll) break; case ECONNRESET: // 连接被对端重置,需要关闭socket close(sockfd); break; default: perror("send failed"); } } else if (ret < len) { // 部分发送成功,需处理剩余数据 buf += ret; len -= ret; } ``` ### 特殊场景 - **信号中断**:如果进程收到信号,可能返回`-1`并设置`errno=EINTR`(需重新调用send) - **MSG_NOSIGNAL**:使用此flag可避免触发`SIGPIPE`信号(收到`EPIPE`错误替代)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值