TCP keepalive保活心跳机制,python和linuc c

方法1 tcp内部keepalive机制

TCP keepalive保活心跳,必须在server端和client端都设置keepalive机制。
因为有发送心跳包,就必须有接收心跳包。两边都需要设置。

python之linux和windows区别

在这里插入图片描述

方法2 tcp_info

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <netinet/tcp.h>


#define PORT 8888   /* server port */
#define MAXDATASIZE 1024

int sockfd;

bool socket_is_connect(int sock)
{
    
    
    struct tcp_info info;
    int len = sizeof(info);

    if(sock <= 0)
    {
    
    
        return false;
    }

    getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
    if((info.tcpi_state == TCP_ESTABLISHED))  //则说明未断开
    {
    
    
        return true;
    }
    else //断开
    {
    
    
        return false;
    }

    return false;
}

bool create_socket()
{
    
    
    struct sockaddr_in server;
    struct timeval timeout = {
    
    5, 0}; // 分别是秒和毫秒

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    
    
        printf("socket() error\n");
        return false;
    }

    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = inet_addr("192.168.9.235");

    if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
    
    
        printf("connect() error\n");
        return false;
    }

    // 发送超时
    setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));

    // 接收超时
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));

    return true;
}

bool send_data()
{
    
    
    int num, real_len, cnt;
    unsigned char buf[MAXDATASIZE] = {
    
    0};

    unsigned char str[] = {
    
    0x55, 0x00, 0x03, 0x62, 0x68, 0x00, 0xCB, 0xAD};
    if(send(sockfd, str, sizeof(str), 0) < 0)
    {
    
    
        printf("send() error\n");
        return false;
    }

    if((cnt = recv(sockfd, buf, MAXDATASIZE, 0)) < 0)
    {
    
    
        printf("recv() error\n");
        return false;
    }

    if(buf[0] == 0x55)
    {
    
    
        real_len = buf[1] << 8 | buf[2] + 5;
        printf("理论数据长度为:%d\n", real_len);
        printf("第一帧数据帧长度为[%d], 数据为:\n", cnt);
        for(int i = 0; i < cnt; i++)
            printf("0x%02X ", buf[i]);  
        printf("\n"); 

        //测试获取功率列表到底分几次返回,当实际接收数据长度大于理论接收数据长度时,即退出循环,不再读取缓冲区
        while(real_len != cnt)
        {
    
    
            if(cnt >= real_len)
                break;

            printf("准备第二次接收\n");
            num = recv(sockfd, &buf[cnt], MAXDATASIZE-cnt, 0);

            printf("第二帧数据帧长度为[%d], 数据为:\n", num);
            for(int i = 0; i < num; i++)
                printf("0x%02X ", buf[cnt+i]);  
            printf("\n"); 

            if(num < 0)
            {
    
    
                printf("second recv() error\n");
                return false;           
            }
            else if (num == 0)
            {
    
    
                printf("无数据可接收\n");
                break;
            }

            cnt += num;
        }
    }
    else
    {
    
    
        printf("第一个字节不是合法标识符\n");
        return false;
    }

    int i;

    printf("接收到的所有数据为:\n");
    for(i = 0; i < cnt; i++)
        printf("0x%02X ", buf[i]);

    printf("\n");

    return true;
}

int main(void)
{
    
    
    bool flag = false;
    if(!create_socket())
    {
    
    
        printf("socket 创建失败,退出程序\n");
        exit(-1);
    }
/*
    while(1)
    {
        if(!socket_is_connect(sockfd))
        {
            printf("socket is broken, reconnect!\n");
            printf("close return:%d\n", close(sockfd));
            sleep(1);
            
            if(create_socket())
            {
                printf("Socket create success again.\n");
                flag = true;
            }
            else
                printf("Socket create failed.\n");
        }


        if(flag){
            send_data();
            flag = false;
        }

        sleep(1);
    }   */
    
    send_data();

    close(sockfd);
    return 0;
}

Guess you like

Origin blog.csdn.net/V__KING__/article/details/120996379