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; }
// 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; }