Socket套接字编程(TCP有限状态机 粘包)

三次握手


四次断开


四次断开特殊情况(同时关闭)


有限状态转换


粘包边界

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

猜你喜欢

转载自blog.csdn.net/qq_33506160/article/details/80397609