如何在C语言中判断socket是否已经断开

yizhihongxing

要在C语言中判断socket是否已经断开,可以通过以下方式实现:

  1. 使用heartbeat机制:

可以使用心跳机制来判断socket是否已经断开。在socket连接建立之后,不断地在两端之间发送心跳包,如果一段时间内没有收到对端的心跳回复,则认为连接已经断开。

以下是使用heartbeat机制的示例代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define HEARTBEAT_INTERVAL 10 // 心跳间隔,单位:秒
#define HEARTBEAT_TIMEOUT 20  // 心跳超时,单位:秒

int main() {
    int sockfd = -1;
    struct sockaddr_in server_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(SERVER_PORT);

    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        close(sockfd);
        return -1;
    }

    printf("Connected to server: %s:%d\n", SERVER_IP, SERVER_PORT);

    // 启动心跳线程
    pthread_t heartbeat_thread;
    pthread_create(&heartbeat_thread, NULL, heartbeat, (void*)&sockfd);

    // 此处可以进行socket通信
    ...

    // 等待心跳线程结束
    pthread_join(heartbeat_thread, NULL);

    close(sockfd);

    return 0;
}

void* heartbeat(void* arg) {
    int sockfd = *(int*)arg;

    while (1) {
        if (send(sockfd, "heartbeat", sizeof("heartbeat"), 0) < 0) {
            fprintf(stderr, "Failed to send heartbeat packet: %s\n", strerror(errno));
            return NULL;
        }

        sleep(HEARTBEAT_INTERVAL);

        // 检查是否收到心跳回复,如果超时则认为socket已经断开
        char buffer[1024] = {0};
        struct timeval timeout;
        fd_set read_fds;

        FD_ZERO(&read_fds);   
        FD_SET(sockfd, &read_fds);  

        timeout.tv_sec = HEARTBEAT_TIMEOUT;
        timeout.tv_usec = 0;

        if (select(sockfd + 1, &read_fds, NULL, NULL, &timeout) == 0) {
            fprintf(stderr, "Heartbeat timeout, socket disconnected\n");
            return NULL;
        }

        if (recv(sockfd, buffer, sizeof(buffer), 0) <= 0) {
            fprintf(stderr, "Failed to receive heartbeat reply: %s\n", strerror(errno));
            return NULL;
        }
    }

    return NULL;
}
  1. 使用select函数:

使用select函数可以监控socket的读事件,如果select返回值为0,则表示socket已经断开。

以下是使用select函数的示例代码:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080

int main() {
    int sockfd = -1;
    struct sockaddr_in server_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(SERVER_PORT);

    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        close(sockfd);
        return -1;
    }

    printf("Connected to server: %s:%d\n", SERVER_IP, SERVER_PORT);

    while (1) {
        fd_set read_fds;
        struct timeval timeout;

        FD_ZERO(&read_fds);
        FD_SET(sockfd, &read_fds);

        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        if (select(sockfd + 1, &read_fds, NULL, NULL, &timeout) <= 0) {
            fprintf(stderr, "Socket disconnected\n");
            break;
        }

        // 接收来自服务器的消息
        ...
    }

    close(sockfd);

    return 0;
}

使用上述两种方式可以有效判断socket是否已经断开,根据不同的需求选择不同的实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何在C语言中判断socket是否已经断开 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 如何在c语言下关闭socket

    关闭socket是确保网络通信中TCP连接正常终止的一项重要步骤。在C语言中,关闭socket的步骤非常简单,下面我将为大家提供一个完整的攻略。 步骤一:创建socket 首先,我们需要创建一个socket对象,用于在Windows或Linux中进行网络通信。在C语言中,可以使用socket()函数来创建socket对象。以下是一个示例: #include …

    C 2023年5月23日
    00
  • PHP使用JSON和将json还原成数组

    关于PHP使用JSON和将JSON还原成数组的攻略,可以分为以下几个步骤: 1. PHP使用JSON 1.1 创建JSON字符串 在PHP中使用json_encode()函数可以将数组转换为JSON格式的字符串。例如: $array = array( ‘name’ => ‘Tom’, ‘age’ => 25, ‘sex’ => ‘male’…

    C 2023年5月23日
    00
  • 魔鬼鱼DR7-PLUS做工值得买吗?未来人类魔鬼鱼DR7-PLUS配置性能全面评测+拆解

    魔鬼鱼DR7-PLUS做工值得买吗? 魔鬼鱼DR7-PLUS是一款高性能台式电脑主机,其做工和性能非常出色,下面我们来详细地评测一下它的配置和性能。 配置 魔鬼鱼DR7-PLUS的配置如下: 处理器:Intel Core i9-11900K(3.5GHz) 显卡:NVIDIA GeForce RTX 3090 24GB 内存:32GB DDR4 3200MH…

    C 2023年5月24日
    00
  • 酷睿i7-9700K处理器玩游戏怎么样 酷睿i7-9700K处理器游戏性能体验评测

    酷睿i7-9700K处理器玩游戏怎么样 介绍 酷睿i7-9700K处理器是英特尔推出的一款高端桌面处理器,采用了基于Coffee Lake架构的9代处理器。该处理器采用了8个物理核心和8个线程,主频频率为3.6GHz,支持Intel® 快速同步视频技术,最高Turbo频率可达到4.9GHz。 测试平台 为了测试该处理器的性能表现,我们搭建了以下测试平台: 处…

    C 2023年5月23日
    00
  • .net中捕捉全局未处理异常的三种方式示例

    接下来我将为你详细讲解如何在.NET中捕捉全局未处理异常,共有三种方式: 方式一:使用UnobservedTaskException事件 使用方式如下: TaskScheduler.UnobservedTaskException += (sender, args) => { // 处理未处理异常的代码 args.SetObserved(); }; 通过…

    C 2023年5月23日
    00
  • 三维模型轻量化方面存在主要问题

    在三维模型轻量化方面,存在一些主要问题,包括: 模型细节丢失:在进行网格简化等操作时,可能会导致模型的细节丢失,使得模型失去原有的质感和细节特征。 模型形变:在进行网格简化等操作时,可能会导致模型形变,使得模型的形状和比例发生变化,影响模型的使用效果。 纹理失真:在进行纹理压缩等操作时,可能会导致纹理失真,使得模型的外观质量受到影响。 模型文件格式问题:不同…

    C语言 2023年4月18日
    00
  • C++中Lambda表达式的语法与实例

    下面是C++中Lambda表达式的语法与实例的详细讲解。 1. Lambda表达式的语法 Lambda 表达式的一般形式如下: [capture list] (parameter list) -> return type { // 函数体 } capture list: 捕获列表,表示可以捕获外部变量,以使用这些变量在 Lambda 表达式中。 par…

    C 2023年5月23日
    00
  • C++核心编程之内存分区详解

    C++核心编程之内存分区详解 C++程序运行时,内存会被划分为几个不同的区域,每个区域都有特定的用途和属性。理解这些内存分区对于程序员来说是非常重要的,因为它可以帮助我们更好地理解代码的执行过程,从而更好地优化代码并避免内存泄漏等问题。 内存分区类型 C++程序运行时,内存主要被分成以下几个区域。 代码区 代码区存储程序的指令,包括函数体的二进制代码。代码区…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部