三次握手
四次断开
四次断开特殊情况(同时关闭)
有限状态转换
粘包边界
TCP产生粘包的原因:
tcp是字节流是无边界的,而udp是消息、数据报,是有边界的。
当对等方进行一次读操作,TCP并不能保证完全把消息读完。而且对方接受数据包的个数是不确定的。
从上图可以看出SQ_SNDBUF 套接字本身有缓冲区 (发送缓冲区、接收缓冲区),tcp传送的网络数据最大值MSS大小限制。链路层也有MTU(最大传送单元)大小限制,如果数据包大于>MTU就要在IP层进行分片,这会导致消息分割。(可以简单的认为MTU是MSS加包头数据)。同时tcp的流量控制和拥塞控制,tcp延迟发送机制等也可能导致粘包。
处理方法
包头加上包体长度(readn/writen)
ssize_t readn(int fd, void *buf, size_t count)
{
size_t nleft = count;
ssize_t nread;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nread == 0) //若对方已关闭
return count - nleft;
bufp += nread;
nleft -= nread;
}
return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft = count;
ssize_t nwritten;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nwritten = write(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}
return count;
}