C语言 socket 编程 close() 和 shutdown() 区别
1、close()关闭文件描述符(包括 socket),立即关闭 socket,对该文件描述符进行“资源回收”。关闭 socket 文件描述符,释放操作系统资源。对于 TCP 连接,close() 会触发 TCP 的 四次挥手(FIN),通知对方你要断开连接。另外,如果对端还未接收数据,可能会造成 RST(重置连接),丢失数据,调用 close() 后该 socket_fd 无法再使用。
#include
#include
#include
#include
#include
int main() {
int sockfd;
struct sockaddr_in server_addr;
char *message = "Hello, server!";
// 创建 socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket 创建失败");
exit(EXIT_FAILURE);
}
// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888); // 服务器端口
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本地服务器
// 连接服务器
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("连接失败");
close(sockfd); // 连接失败时也要关闭 socket
exit(EXIT_FAILURE);
}
// 发送消息
send(sockfd, message, strlen(message), 0);
printf("消息已发送,关闭 socket。\n");
// 关闭 socket
close(sockfd);
return 0;
}
2、shutdown()shutdown() 函数用于 部分或完全关闭一个 socket 的连接。它比 close() 更灵活,可以单独关闭 读通道、写通道,或 全部关闭。
int shutdown(int sockfd, int how);
sockfd 套接字描述符,how 指定关闭的方式。常用的有:
SHUT_RD(0)关闭读操作。不能再接收数据。
SHUT_WR(1)关闭写操作。不能再发送数据。
SHUT_RDWR(2)同时关闭读和写。
#include
#include
#include
#include
#include
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12345);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
// 发送请求
const char *msg = "Hello, server!";
send(sock, msg, strlen(msg), 0);
// 关闭写通道,告诉服务器不再发送数据
shutdown(sock, SHUT_WR);
// 接收服务器回应
char buffer[1024];
int len = recv(sock, buffer, sizeof(buffer)-1, 0);
buffer[len] = '\0';
printf("收到回应: %s\n", buffer);
// 关闭 socket
close(sock);
return 0;
}
3、close() 和 shutdown() 区别close() 和 shutdown() 都用于关闭 socket,但它们的行为和应用场景不同。
特性/行为
close()
shutdown()
作用范围
立即关闭 socket 的读写功能及释放文件描述符
按指定方式关闭 socket 的读/写功能,不立即释放描述符
关闭粒度
一刀切,不能细分
可选择关闭
读
、
写
、或
读写
通道
是否释放资源
是,释放文件描述符
否,仅关闭指定通道,仍需调用
close()
释放资源
是否可继续使用
否,调用后文件描述符无效
是,可根据关闭方式继续读或写
常见用途
程序结束时彻底释放 socket
通讯中半关闭连接(如 TCP 四次挥手中的 FIN)
系统调用行为
会递减引用计数,最后一个引用才会关闭连接
不影响引用计数,仅断开通道
