完整的应用心跳服务应该包含哪些方面( 二 )
下面我们通过一个实例来展示心跳机制。
结构,一个客户程序,和一个服务程序。步骤:服务器:1.经过socket、bind、listen、后用accept获取一个客户的连接请求,为了简单直观,这里服务器程序只接收一个connect请求,我们用clifd来获取唯一的一个连接。2.为clifd修改KeepAlive的相关参数,并开启KeepAlive套接字选项,这里我们把间隔时间设为了5秒,闲置时间设置了5秒,探测次数设置为5次。3.将clifd加入select监听的描述符号集客户:很简单,只是连接上去,并停留在while死循环。方式:服务程序放到阿里云服务器上,我们执行服务程序并将输出结果重定向到一个日志文件,目的是为了将我们本地网络连接断开后,超过了keepalive闲置时间+重复发包探测的时间后,重新打开本地的网络连接,并登录服务器,通过该日志文件的内容来查看程序的打印结果。 1 #include \u0026lt;iostream\u0026gt; 2 #include \u0026lt;sys/types.h\u0026gt; 3 #include \u0026lt;sys/socket.h\u0026gt; 4 #include \u0026lt;stdlib.h\u0026gt; 5 #include \u0026lt;strings.h\u0026gt; 6 #include \u0026lt;stdio.h\u0026gt; 7 #include \u0026lt;netinet/in.h\u0026gt; 8 #include \u0026lt;arpa/inet.h\u0026gt; 9 #include \u0026lt;errno.h\u0026gt; 10 #include \u0026lt;unistd.h\u0026gt; 11 using namespace std; 12 13 int main() 14 { 15 int skfd; 16 if ((skfd = socket(AF_INET, SOCK_STREAM, 0)) \u0026lt; 0) { 17 perror(""); 18 exit(-1); 19 } 20 21 struct sockaddr_in saddr; 22 bzero(\u0026amp;saddr, sizeof(saddr)); 23 saddr.sin_family = AF_INET; 24 saddr.sin_port = htons(9999); 25 saddr.sin_addr.s_addr = inet_addr("115.29.109.198"); 26 27 if (connect(skfd, (struct sockaddr*)\u0026amp;saddr, sizeof(saddr)) \u0026lt; 0) { 28 perror(""); 29 exit(-1); 30 } 31 32 cout \u0026lt;\u0026lt; "连接成功" \u0026lt;\u0026lt; endl; 33 while(1); 34 return 0; 35 } 36 服务器 37 38 #include \u0026lt;iostream\u0026gt; 39 #include \u0026lt;sys/types.h\u0026gt; 40 #include \u0026lt;sys/socket.h\u0026gt; 41 #include \u0026lt;stdlib.h\u0026gt; 42 #include \u0026lt;strings.h\u0026gt; 43 #include \u0026lt;stdio.h\u0026gt; 44 #include \u0026lt;netinet/in.h\u0026gt; 45 #include \u0026lt;arpa/inet.h\u0026gt; 46 #include \u0026lt;errno.h\u0026gt; 47 #include \u0026lt;unistd.h\u0026gt; 48 #include \u0026lt;sys/select.h\u0026gt; 49 #include \u0026lt;netinet/tcp.h\u0026gt; 50 using namespace std; 51 52 #define LISTENNUM 5 53 54 int main() 55 { 56 int skfd; 57 if ((skfd = socket(AF_INET, SOCK_STREAM, 0)) \u0026lt; 0) { 58 perror(""); 59 exit(-1); 60 } 61 62 struct sockaddr_in saddr; 63 bzero(\u0026amp;saddr, sizeof(saddr)); 64 saddr.sin_family = AF_INET; 65 saddr.sin_port = htons(9999); 66 saddr.sin_addr.s_addr = inet_addr("115.29.109.198"); 67 68 if (bind(skfd, (struct sockaddr*)\u0026amp;saddr, sizeof(saddr)) \u0026lt; 0) { 69 perror(""); 70 exit(-1); 71 } 72 73 if (listen(skfd, LISTENNUM) \u0026lt; 0) { 74 perror(""); 75 exit(-1); 76 } 77 78 int clifd; 79 if ((clifd = accept(skfd, NULL, NULL)) \u0026lt; 0) { 80 perror(""); 81 exit(-1); 82 } 83 cout \u0026lt;\u0026lt; "有新连接" \u0026lt;\u0026lt; endl; 84 85 //setsockopt 86 int tcp_keepalive_intvl = 5; //保活探测消息的发送频率。默认值为75s 87 int tcp_keepalive_probes = 5; //TCP发送保活探测消息以确定连接是否已断开的次数。默认值为9次 88 int tcp_keepalive_time = 5; //允许的持续空闲时间。默认值为7200s(2h) 89 int tcp_keepalive_on = 1; 90 91 if (setsockopt(clifd, SOL_TCP, TCP_KEEPINTVL, 92 \u0026amp;tcp_keepalive_intvl, sizeof(tcp_keepalive_intvl)) \u0026lt; 0) { 93 perror(""); 94 exit(-1); 95 } 96 97 if (setsockopt(clifd, SOL_TCP, TCP_KEEPCNT, 98 \u0026amp;tcp_keepalive_probes, sizeof(tcp_keepalive_probes)) \u0026lt; 0) { 99 perror("");100 exit(-1);101 }102 103 if (setsockopt(clifd, SOL_TCP, TCP_KEEPIDLE,104 \u0026amp;tcp_keepalive_time, sizeof(tcp_keepalive_time)) \u0026lt; 0) {105 perror("");106 exit(-1);107 }108 109 if (setsockopt(clifd, SOL_SOCKET, SO_KEEPALIVE,110 \u0026amp;tcp_keepalive_on, sizeof(tcp_keepalive_on))) {111 perror("");112 exit(-1);113 }114 115 char buf;116 int r;117 int maxfd;118 fd_set rset;119 FD_ZERO(\u0026amp;rset);120 sleep(5);121 while (1) {122 FD_SET(clifd, \u0026amp;rset);123 maxfd = clifd + 1;124 if (select(maxfd, \u0026amp;rset, NULL, NULL, NULL) \u0026lt; 0) {125 perror("");126 exit(-1);127 }128 129 if (FD_ISSET(clifd, \u0026amp;rset)) {130 r = read(clifd, buf, sizeof(buf));131 if (r == 0) {132 cout \u0026lt;\u0026lt; "接收到FIN" \u0026lt;\u0026lt; endl;133 close(clifd);134 break;135 }136 else if (r == -1) {137 if (errno == EINTR) {138 cout \u0026lt;\u0026lt; "errno: EINTR" \u0026lt;\u0026lt; endl;139 continue;140 }141 142 if (errno == ECONNRESET) {143 cout \u0026lt;\u0026lt; "errno: ECONNRESET" \u0026lt;\u0026lt; endl;144 cout \u0026lt;\u0026lt; "对端已崩溃且已重新启动" \u0026lt;\u0026lt; endl;145 close(clifd);146 break;147 }148 149 if (errno == ETIMEDOUT) {150 cout \u0026lt;\u0026lt; "errno: ETIMEDOUT" \u0026lt;\u0026lt; endl;151 cout \u0026lt;\u0026lt; "对端主机崩溃" \u0026lt;\u0026lt; endl;152 close(clifd);153 break;154 }155 156 if (errno == EHOSTUNREACH) {157 cout \u0026lt;\u0026lt; "errno: EHOSTUNREACH" \u0026lt;\u0026lt; endl;158 cout \u0026lt;\u0026lt; "对端主机不可达" \u0026lt;\u0026lt; endl;159 close(clifd);160 break;161 }162 }163 }164 }165 166 close(skfd);167 return 0;168 }
推荐阅读
- 想寒假的时候一个月在家准备计算机二级的office高级应用,但是不知道买啥书比较好~~~?
- 蓝牙路由器在医疗健康方面有哪些应用
- ibeacon目前在国内有已经应用或者商用的产品案例吗
- 如果 WP 手机可以运行 exe 应用程序,那将会是怎么样的效果可行吗
- linux 应用层可以使用DMA进行数据传输吗
- 京东,天猫这类购物商城为啥不做成单页应用?
- when|九年级英语定语从句完整归纳讲解及练习
- 计算机视觉在互联网、电子商务中有哪些应用前景
- 为啥我无法保存一个网页的完整html文件
- 将ipad应用于课堂是利大于弊还是弊大于利
