TCP是个流协议,所谓流就是没有界限的一串数据。
TCP底层不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以一个完整的包可能会被TCP拆分成多个包进行发送(拆包),或者多个小的包被封装成一个大的数据包发送(粘包)。
由于底层的TCP无法理解上层的业务数据,所以在底层无法保证数据包不被拆分和重组,只能通过上层的应用协议栈设计来解决。
1.在包尾增加特殊符号分割
2.将消息分为消息头和消息体,消息头中包含消息总长度。
心跳检测分类:
1.TCP的keep-alive机制:N次发送心跳检测消息时没有收到应答或直接发生IO异常则说明链路失效
只能检测连接的死活,不能检测到通信两端的的存活状态
netty的心跳检测机制是利用链路空闲检测机制实现,超过指定时间没有收到心跳检测消息则触发IdleStateEvent事件,用户订阅IdleStateEvent事件自定义逻辑处理,如关闭链接,重新发起连接,告警等。
2.一些长链接协议如SMPP的心跳检测,还有IM即时通讯的一些协议的心跳检测
3.业务方自定义的心跳消息实现
TCP协议使用心跳检测来判断对方是否还存活着:http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#whatis
int set_tcp_keepAlive(int fd, int start, int interval, int count)
{
int keepAlive = 1;
if (fd < 0 || start < 0 || interval < 0 || count < 0) return -1; //入口参数检查 ,编程的好惯。
//启用心跳机制,如果您想关闭,将keepAlive置零即可
if(setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1)
{
perror("setsockopt");
return -1;
}
//启用心跳机制开始到首次心跳侦测包发送之间的空闲时间
if(setsockopt(fd,SOL_TCP,TCP_KEEPIDLE,(void *)&start,sizeof(start)) == -1)
{
perror("setsockopt");
return -1;
}
//两次心跳侦测包之间的间隔时间
if(setsockopt(fd,SOL_TCP,TCP_KEEPINTVL,(void *)&interval,sizeof(interval)) == -1)
{
perror("setsockopt");
return -1;
}
//探测次数,即将几次探测失败判定为TCP断开
if(setsockopt(fd,SOL_TCP,TCP_KEEPCNT,(void *)&count,sizeof(count)) == -1)
{
perror("setsockopt");
return -1;
}
return 0;
}