TCP Socket文件传输的粘包问题及解决


基于TCP网络传输的应用程序有时会出现粘包现象(即发送方发送的若干包数据到接收方接收时粘成一包)


TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

  出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据(图1所示)。


图1


图2


图3

  粘包情况有两种,一种是粘在一起的包都是完整的数据包(图1、图2所示),另一种情况是粘在一起的包有不完整的包(图3所示),此处假设用户接收缓冲区长度为m个字节。

  不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。

实际解决

接受端

                        int iRecvSize = PackteSize + 10;
                        int iRet;
                        int idx = 0;
			while (iRecvSize > 0)
			{
				iRet = recv(AcceptSocket, recvbuf+idx, iRecvSize, 0);
				if (iRet > 0)
				{
					idx += iRet;
					iRecvSize -= iRet;
				}
				else if (iRet == 0)
				{
					break;
				}
				else if ( iRet == SOCKET_ERROR)
				{
					break;
				}
			}


发送端

	                int iSendSize = PacketSize + 10;
			int iSent;
                        int idx = 0;
			while (iSendSize > 0)
			{
				iSent = send(m_socket,sendbuffer+idx,iSendSize,0);
				if (iSent > 0)
				{
					idx += iSent;
					iSendSize -= iSent;
				}
				else if (iSent == 0)
				{
					break;
				}
				else if (iSent == SOCKET_ERROR)
				{
					wprintf(L"send failed with error: %d\n", WSAGetLastError());
					//closesocket(m_socket);
					//WSACleanup();
					break;
				}
			}

这种加强版的send,和 recv可以处理这种粘包而产生的传输而导致的数据错误。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值