程序实现心跳包检测机制
  首先要在备份机和源机之间建立一个专门的socket链路来进行心跳检测。
  在源机端,在进行数据迁移之前,会建立一个socket来监听备份机的连接,并将这个socket和对应的处理函数放入原软件的io处理列表中,代码如下:
int listenfd;
struct sockaddr_in server_sin;
/* establish socket */
listenfd=socket(AF_INET,SOCK_STREAM,0);
server_sin.sin_family=AF_INET;
server_sin.sin_addr.s_addr=htonl(INADDR_ANY);
server_sin.sin_port=htons(PORT);
bind(listenfd,(struct sockaddr *)&server_sin,sizeof(server_sin));
/* establish end */
listen(listenfd,1024);
qemu_set_fd_handler2(listenfd, NULL, tcpkeepalive_server, NULL,
(void *)(intptr_t)listenfd);
  该socket对应的处理函数如下:
static void tcpkeepalive_server(void *opaque)
{
int connfd;
struct sockaddr_in client_sin;
socklen_t client_len=sizeof(client_sin);
int listenfd = (intptr_t)opaque;
connfd=accept(listenfd,(struct sockaddr *)&client_sin,&client_len);
}
  在备份机端,当其开始作为备份机时,会建立socket连接源机的监听端,并设置对应的tcpkeepalive参数,然后将socket和对应的处理函数加入io处理列表。
  我们建立的socket是一个心跳检测专用链路,其上不会有数据流动,只有一种情况备份机端会收到数据,那是源端出现了故障,tcpkeepalive机制会返回一个错误信息,所以捕捉到了这个信息,备份机会跳转到对应的处理函数,接替源机开始运行。
  对应代码如下:
int sockfd;
struct sockaddr_in sin;
int optval;
socklen_t optlen = sizeof(optval);
sockfd=socket(AF_INET,SOCK_STREAM,0);
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=addr.sin_addr.s_addr;
sin.sin_port=htons(PORT);
optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
optval = 5;
setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &optval, optlen);
optval = 1;
setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen);
optval = 1;
setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen);
connect(sockfd,(struct sockaddr *)&sin,sizeof(sin));
qemu_set_fd_handler2(sockfd, NULL, tcpkeepalive_vm_start, NULL,
(void *)(intptr_t)sockfd);
  该socket对应的处理函数很简单,是让备份机开始运行:
  static void tcpkeepalive_vm_start(void *opaque)
  {
  vm_start();
  }