(OK) C/S—心跳检测—heartbeat

/root/桌面/server-client-pthread-c

heartbeat-server.c



    // gcc heartbeat-server.c -o heartbeat-server
    // indent -npro -kr -i8 -ts8 -sob -l280 -ss -ncs -cp1 *
    /* heartbeat-server.c
     *
     * improved by ztguang, 2015.12.20
     *
     * Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in
     * whole or in part in accordance to the General Public License (GPL).
     *
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.
    */
    /*****************************************************************************/
    /*** heartbeat-server.c ***/
    /*** ***/
    /*** Demonstrates how to keep track of the server using a "heartbeat". If ***/
    /*** the heartbeat is lost, the connection can be reestablished and the ***/
    /*** session resumed. ***/
    /*****************************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <strings.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <resolv.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>

    #define BUF_SIZE 1024            //默认缓冲区
    #define SERVER_PORT 11111        //监听端口
    #define SERVER_HOST "127.0.0.1"    //服务器IP地址
    #define LISTEN_SIZE 10            //监听队列长度

    //两个有用的宏定义:检查和赋值并且检测
    #define CHK(eval) if(eval < 0){perror("eval"); exit(-1);}
    #define CHK2(res, eval) if((res = eval) < 0){perror("eval"); exit(-1);}

    int client;
    struct sigaction act;
    /*---------------------------------------------------------------------
        sig_handler - catch and send heartbeat.
     ---------------------------------------------------------------------*/
    void sig_handler(int signum)
    {
        if (signum == SIGURG) {
            char c;
            recv(client, &c, sizeof(c), MSG_OOB);
            if (c == '?')
                /* Are you alive? */
                send(client, "Y", 1, MSG_OOB);    /* */
        } else if (signum == SIGCHLD)
            wait(0);
    }

    /*---------------------------------------------------------------------
        servlet - process requests
     ---------------------------------------------------------------------*/
    void servlet(void)
    {
        int bytes;
        char buffer[BUF_SIZE];
        bzero(&act, sizeof(act));
        act.sa_handler = sig_handler;
        act.sa_flags = SA_RESTART;
        sigaction(SIGURG, &act, 0);    /* connect SIGURG signal */
        if (fcntl(client, F_SETOWN, getpid()) != 0)
            perror("Can't claim SIGIO and SIGURG");
        do {
            bzero(buffer, BUF_SIZE);
            bytes = recv(client, buffer, sizeof(buffer), 0);
            printf("recieve [%s] from client-%d\n", buffer, client);
            if (bytes > 0)
                send(client, buffer, bytes, 0);
        } while (bytes > 0);

        printf("end while\n");

        close(client);
        exit(0);
    }

    /*---------------------------------------------------------------------
        main - set up client and begin the heartbeat.
     ---------------------------------------------------------------------*/
    int main(int count, char *strings[])
    {
        bzero(&act, sizeof(act));
        act.sa_handler = sig_handler;
        act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
        if (sigaction(SIGCHLD, &act, 0) != 0)
            perror("sigaction()");

        int listener;        //监听socket
        struct sockaddr_in addr, peer;
        addr.sin_family = PF_INET;
        addr.sin_port = htons(SERVER_PORT);
        addr.sin_addr.s_addr = inet_addr(SERVER_HOST);
        socklen_t socklen;
        socklen = sizeof(struct sockaddr_in);
        CHK2(listener, socket(PF_INET, SOCK_STREAM, 0));    //初始化监听socket

        // 设置套接字选项避免地址使用错误
        int on = 1;
        if ((setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
            perror("server: setsockopt failed");
            exit(EXIT_FAILURE);
        }

        CHK(bind(listener, (struct sockaddr *)&addr, sizeof(addr)));    //绑定监听socket

        //printf("listen\n");
        CHK(listen(listener, LISTEN_SIZE));    //设置监听
        printf("server: listening\n");

        while (1) {
            client = accept(listener, (struct sockaddr *)&peer, &socklen);
            printf("accept client-%d\n", client);
            if (client > 0) {
                if (fork() == 0) {
                    close(listener);
                    servlet();
                } else
                    close(client);
            } else
                perror("accept()");
        }
        close(client);
        return 0;
    }


heartbeat-client.c


    // gcc heartbeat-client.c -o heartbeat-client
    // indent -npro -kr -i8 -ts8 -sob -l280 -ss -ncs -cp1 *
    /* heartbeat-client.c
     *
     * improved by ztguang, 2015.12.20
     *
     * Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in
     * whole or in part in accordance to the General Public License (GPL).
     *
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.
    */
    /*****************************************************************************/
    /*** heartbeat-client.c ***/
    /*** ***/
    /*** Demonstrates how to keep track of the server using a "heartbeat". If ***/
    /*** the heartbeat is lost, the connection can be reestablished and the ***/
    /*** session resumed. ***/
    /*****************************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <resolv.h>
    #include <netinet/tcp.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>

    #define SERVER_PORT 11111    //监听端口
    #define SERVER_HOST "127.0.0.1"    //服务器IP地址
    #define DELAY 2            /*seconds */

    //两个有用的宏定义:检查和赋值并且检测
    #define CHK(eval) if(eval < 0){perror("eval"); exit(-1);}
    #define CHK2(res, eval) if((res = eval) < 0){perror("eval"); exit(-1);}

    int serverfd, got_reply = 1;

    /*---------------------------------------------------------------------
        sig_handler - if the single is OOB, set flag. If ALARM, send heartbeat.
     ---------------------------------------------------------------------*/
    void sig_handler(int signum)
    {
        int bytes, len;

        struct tcp_info info;
        int leng = sizeof(info);

        if (signum == SIGURG) {
    //*
            getsockopt(serverfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *) &leng);
            if ((info.tcpi_state == TCP_ESTABLISHED)) {        // socket connected
                ; //return 1;
            } else {        // socket disconnected
                return;
            }
    //*/
            char c;
            CHK2(bytes, recv(serverfd, &c, sizeof(c), MSG_OOB));
            if (bytes == 0) return;

            got_reply = (c == 'Y');    /* Got reply */
            fprintf(stderr, "[server is alive]\n");
        } else if (signum == SIGALRM) {
            printf("reply = %d\n", got_reply);
            if (got_reply) {
                alarm(DELAY);    // Wait a while
    //*
                getsockopt(serverfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *) &leng);
                if ((info.tcpi_state == TCP_ESTABLISHED)) {        // socket connected
                    ; //return 1;
                } else {        // socket disconnected
                    return;
                }
    //*/
                CHK2(len, send(serverfd, "?", 1, MSG_OOB));        // Alive??
                if (len == 0) return;
                got_reply = 0;
            } else {
                fprintf(stderr, "Lost connection to server!\n");
                alarm(DELAY);    /* Wait a while */
            }
        }
    }

    /*---------------------------------------------------------------------
        main - set up client and begin the heartbeat.
     ---------------------------------------------------------------------*/
    int main(int count, char *strings[])
    {

        int bytes, len;
        char line[100];

        struct tcp_info info;
        int leng = sizeof(info);

        struct sigaction act;
        bzero(&act, sizeof(act));
        act.sa_handler = sig_handler;
        act.sa_flags = SA_RESTART;
        sigaction(SIGURG, &act, 0);
        sigaction(SIGALRM, &act, 0);

        struct sockaddr_in seraddr;
        seraddr.sin_family = PF_INET;
        seraddr.sin_port = htons(SERVER_PORT);
        seraddr.sin_addr.s_addr = inet_addr(SERVER_HOST);

        CHK2(serverfd, socket(PF_INET, SOCK_STREAM, 0));
        if (fcntl(serverfd, F_SETOWN, getpid()) != 0)    // claim SIGIO/SIGURG signals
            perror("Can't claim SIGURG and SIGIO");

        while (1)
        {
            got_reply = 1;

            close(serverfd);
            CHK2(serverfd, socket(PF_INET, SOCK_STREAM, 0));
            if (fcntl(serverfd, F_SETOWN, getpid()) != 0) {        // claim SIGIO/SIGURG signals
                perror("Can't claim SIGURG and SIGIO");
                continue;
            }

            if (connect(serverfd, (struct sockaddr *)&seraddr, sizeof(seraddr)) == 0) {
                printf("connect [OK]\n");
                alarm(DELAY);
                do {
    //*
                    getsockopt(serverfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *) &leng);
                    if ((info.tcpi_state == TCP_ESTABLISHED)) {        // socket connected
                        ; //return 1;
                    } else {        // socket disconnected
                        break;
                    }
    //*/
                    //CHK2(len, send(serverfd, "?", 1, MSG_OOB));        // Alive??
                    //got_reply = 0;
                    //CHK2(len, send(serverfd, "restart", 7, 0));
                    //printf("send [restart]\n");
                    memset(line, 0x00, 100);
                    gets(line);
                    printf("send [%s]\n", line);
                    //CHK2(len, send(serverfd, "adsf", 4, 0)); sleep(1);

                    CHK2(len, send(serverfd, line, strlen(line), 0));        // send
                    if (len <= 0) break;

                    CHK2(bytes, recv(serverfd, line, sizeof(line), 0));        // recieve
                    if (bytes <= 0) break;

                } while (bytes > 0);

                printf("end while\n");

            } else {
                perror("connect failed, retry!\n");
                sleep(2);
            }
        }
        //close(serverfd);
        //return 0;
    }




posted @ 2016-04-02 09:51  张同光  阅读(260)  评论(0编辑  收藏  举报