C 的 socket 编程中,两种方式关闭 socket,close(socket_fd) 和 shutdown(socket_fd, how)都与关闭套接字相关,但用途和作用不完全一样。在调用 shutdown() 后,仍需调用 close() 来释放 socket 的文件描述符。

1、close()

关闭文件描述符(包括 socket),立即关闭 socket,对该文件描述符进行“资源回收”。关闭 socket 文件描述符,释放操作系统资源。对于 TCP 连接,close() 会触发 TCP 的 四次挥手(FIN),通知对方你要断开连接。另外,如果对端还未接收数据,可能会造成 RST(重置连接),丢失数据,调用 close() 后该 socket_fd 无法再使用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>       // 包含 close()
#include <arpa/inet.h>    // 包含 socket 相关函数

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 <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

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)

系统调用行为

会递减引用计数,最后一个引用才会关闭连接

不影响引用计数,仅断开通道

推荐文档

相关文档

大家感兴趣的内容

随机列表