当前位置: 首页 > news >正文

close函数概念和使用案例

在 socket 编程中,close 函数是用于释放套接字资源的核心系统调用,其作用是终止套接字的连接并释放相关内核资源(如文件描述符、缓冲区等)。它是 UNIX 系统中通用的文件描述符关闭函数,不仅适用于 socket,也适用于普通文件、管道等,但在网络编程中有着特殊的语义和注意事项。

一、函数原型与头文件

#include <unistd.h>  // 必须包含的头文件
int close(int fd);

二、参数解析:fd(文件描述符)

  • 含义:需要关闭的套接字描述符(由 socket()accept() 函数返回的整数)。
  • 取值范围
    有效范围通常是 0 ~ OPEN_MAX(系统限制的最大文件描述符数量,可通过 getrlimit 查看)。
    常见有效取值为非负整数(0 通常是标准输入,1 标准输出,2 标准错误,套接字描述符一般从 3 开始)。
  • 约束
    • 必须是已打开且未关闭的有效套接字描述符(否则会触发 EBADF 错误)。
    • 不能是已关闭的描述符(重复关闭会导致未定义行为,通常返回错误)。

三、返回值解析

  • 成功:返回 0,表示套接字资源已被成功释放。
  • 失败:返回 -1,并设置全局变量 errno 表示具体错误原因(可通过 perror()strerror(errno) 打印)。
常见错误码(errno)及含义:
错误码含义典型场景
EBADF无效的文件描述符(fd 未打开或已关闭)对已关闭的套接字调用 closefd 为负数
EINTR调用被信号中断关闭过程中收到信号(如 SIGINT
EIOI/O 错误(罕见)关闭时发生底层 I/O 异常

四、close 在 socket 中的核心行为

close 对套接字的操作本质是“释放资源 + 终止连接”,但具体行为因协议(TCP/UDP)和连接状态而异:

1. 对 TCP 套接字的影响(面向连接)

TCP 是面向连接的协议,close 会触发双向关闭流程(四次挥手):

  • 关闭后,套接字不再允许读写操作(调用 read/write 会返回错误)。
  • 内核会尽力发送发送缓冲区中剩余的数据,并等待对方确认(确保数据不丢失)。
  • 释放套接字的文件描述符,使其可被系统重新分配给新的 opensocket 调用。

注意:TCP 的 close 是“全双工关闭”——既关闭读方向,也关闭写方向。如果需要只关闭一个方向(如只禁止发送但保留接收),需使用 shutdown 函数(而非 close)。

2. 对 UDP 套接字的影响(无连接)

UDP 是无连接协议,没有“挥手”过程,close 的行为更简单:

  • 直接释放套接字资源(发送/接收缓冲区被清空)。
  • 后续无法再通过该套接字发送或接收数据。
3. 与 shutdown 的关键区别

closeshutdown 都可终止连接,但核心差异在于“资源释放”和“方向控制”:

特性close(int fd)shutdown(int fd, int how)
资源释放释放文件描述符(引用计数减 1,为 0 时真正关闭)不释放文件描述符,仅关闭连接方向
方向控制全双工关闭(读写均不可用)可选择关闭读(SHUT_RD)、写(SHUT_WR)或全关(SHUT_RDWR
多进程共享仅最后一个 close 会真正关闭连接(因引用计数)无论引用计数,立即关闭指定方向

五、使用场景与最佳实践

1. 客户端主动断开连接

客户端完成数据交互后,需调用 close 释放套接字,避免资源泄漏:

// 客户端示例:发送数据后关闭连接
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
send(sockfd, "hello", 5, 0);  // 发送数据
close(sockfd);  // 完成后关闭套接字,释放资源
2. 服务器关闭客户端连接

服务器处理完一个客户端请求后,需关闭对应客户端的套接字(保留监听套接字继续接受新连接):

// 服务器示例:处理客户端后关闭连接
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_fd, ...);
listen(listen_fd, 10);while (1) {int client_fd = accept(listen_fd, ...);  // 接受新连接// 处理客户端请求(如 read/write)close(client_fd);  // 处理完后关闭客户端套接字
}
3. 异常场景下的资源释放

当网络出错(如连接超时、对方断开)时,需主动关闭套接字,避免资源泄漏:

// 错误处理示例
ssize_t n = recv(client_fd, buf, sizeof(buf), 0);
if (n <= 0) {  // 连接关闭或出错if (n < 0) perror("recv error");close(client_fd);  // 释放错误连接的资源
}

六、注意事项

  1. 避免重复关闭:对同一套接字多次调用 close 会导致 EBADF 错误(第二次关闭时 fd 已无效)。

    close(sockfd);
    close(sockfd);  // 错误:重复关闭,返回 -1,errno=EBADF
    
  2. TIME_WAIT 状态的影响
    TCP 连接中,主动关闭的一方会进入 TIME_WAIT 状态(默认约 60 秒),确保最后一个确认包被接收。此时 close 已返回,但端口可能暂时无法重用(需结合 SO_REUSEADDR 选项解决)。

  3. 引用计数问题
    若多个进程/线程共享同一套接字(如 fork 后子进程继承 fd),close 仅减少引用计数,只有最后一次 close 才会真正关闭连接。如需强制关闭,需用 shutdown

  4. 错误处理不可忽略
    虽然 close 失败概率较低,但在关键场景(如服务器长期运行)中需检查返回值,避免资源泄漏:

    if (close(sockfd) == -1) {perror("close failed");  // 记录错误日志
    }
    

总结

close 函数是 socket 编程中释放资源的“最后一步”,其核心作用是终止套接字连接并释放文件描述符。在使用时需注意:

  • 区分 TCP(双向关闭、四次挥手)和 UDP(直接释放)的不同行为;
  • shutdown 配合使用(如需单方向关闭);
  • 避免重复关闭,正确处理错误以防止资源泄漏。

合理使用 close 是编写健壮网络程序的基础。

http://www.dtcms.com/a/332071.html

相关文章:

  • rustdesk 开源遥控软件
  • 云服务器运行持续强化学习COOM框架的问题
  • 低配硬件运行智谱GLM-4.5V视觉语言模型推理服务的方法
  • C#WPF实战出真汁01--项目介绍
  • linux设备驱动之USB驱动-USB主机、设备与Gadget驱动
  • 【Java|第十九篇】面向对象九——String类和枚举类
  • AI更换商品背景,智能融合,无痕修图
  • Java中加载语义模型
  • Windows bypassUAC 提权技法详解(一)
  • 洗浴中心泡池水过滤系统原理深度解析与工程实践
  • RocketMQ 4.9.3源码解读-客户端Consumer消费者组件启动流程分析
  • 具身智能Scaling Law缺失:机器人界的“摩尔定律“何时诞生?
  • Ansible企业级实战
  • centos部署chrome和chromedriver
  • C#WPF实战出真汁03--登录界面设计
  • C#WPF实战出真汁04--登录功能实现
  • 单目操作符与逗号表达式
  • CoreShop商城框架开启多租户(2)
  • 莫队 + 离散化 Ann and Books
  • 【19-模型训练细节 】
  • 业务敏捷性对SAP驱动型企业意味着什么?如何保持企业敏捷性?
  • 零信任架构(Zero Trust Architecture, ZTA)(通过动态验证和最小权限控制,实现对所有访问请求的严格授权和持续监控)
  • latex 中破折号的输入
  • 介绍java中atomic及相关类
  • PERC初探暨小试牛刀
  • Vue3 vxeTree树形组件完全指南:从入门到精通的完整使用教程
  • QT6(可视化UI设计代码实现)
  • MATLAB实现图像增强(直方图均衡化)
  • 数学分析| 极限论| 1.数列极限常用方法总结
  • App冷启动阶段Open Dexfiles实现原理【ART虚拟机系列2】