TCP通信,recv接收数据需要注意的地方?

        关于TCP通信中,recv函数接收数据大小的问题,之前一直觉得,只要是客户端与服务器一发一收的模式,那么recv接收的数据大小一定是函数中指定的数据大小。这次写了客户端与服务器通信的程序,在这上面栽了一个大跟斗。
        程序功能如下:通过客户端与服务器的通信,实现文件的传输,客户端每次发送1k的数据,服务器每次接收1k大小数据并将数据存储到文件中,就这样一发一收的循环发送接收,实现了文件的拷贝。
        但在实际的测试中,发现不能实现文件的拷贝,因为对每个1k大小的发送包都编了序号,发现在传输的过程出现了错误,但TCP是的宗旨是可靠传输,这就相互矛盾了。为此我到网上去搜索相关信息,看广大网友对此的看法以及解决方法。在网上搜索的信息不多,只发现一个解决该问题方法,那就是让服务器sleep一秒,我将服务器睡眠一秒后运行,发现是能够解决一点问题,但只能将错误的概率减少,不能彻底解决问题。
        既然网上暂时没有找到解决方法,我只能够自己慢慢测试了。因为之前觉得TCP的可靠带着recv一起可靠了所以没有对返回值进行判断,现在加上对返回值的判断,发现 错误传输时,recv返回值只有几百K(所以说一定一定要对函数返回值进行判断,这样能减少程序BUG,也能更加快速找到问题所在),发现问题所在了。 原来当recv去接收时,内核只传送了几百k到用户空间,并没有传送1k(至于为什么会这样,我就不得知道了,没有去深究),这样我对返回值进行判断,等于指定值时,就接着循环接收,少于指定值时,多加一个循环结束,直到将1K全部接收为止,这样就完美的解决了,部分代码如下

while (1)
	{
		memset(&recv_buf, 0, sizeof(DATA));
		recv_back = recv(client_fd, &recv_buf, sizeof(DATA), 0);

		if ((0 == recv_back) || (recv_back < 0))
		{
			perror("fail to recv");
			break;
		}

		#if 1
		/* 判断数据是否接收完整 */
		if (recv_back < sizeof(DATA))
		{
			remain_data_size = 1036 - recv_back; // 剩余数据长度

			while (1)
			{
				printf("recv_back = %d\n", recv_back);
				memset(data_buf, 0, sizeof(data_buf));
				recv_back = recv(client_fd, data_buf, remain_data_size, 0);
				printf("recv_back = %d\n", recv_back);
				if ((0 == recv_back) || (recv_back < 0))
				{
					perror("fail to recv");
					break;
				}

				m = 1036 - remain_data_size - 4; // m为上一次接收得数据量 - 4
				for (n = 0; n < remain_data_size; n++)
				{
					k = m + n;
					if (k > 1023 && k < 1028) // size
					{
						//printf("size data_buf[%d] = %d\n", n, data_buf[n]);
						recv_buf.size = recv_buf.size + (data_buf[n] << ((k - 1024) * 8));
					}
					else if (k >= 1028) // num
					{
						//printf("num data_buf[%d] = %d\n", n, data_buf[n]);
						recv_buf.num = recv_buf.num + (data_buf[n] << ((k - 1028) * 8));
					}
					else
					{
						recv_buf.data[k] = data_buf[n];
					}
				}
				/* 当两个值相等时,代表数据接收完毕 */
				if (recv_back == remain_data_size)
				{
					printf("size = %d num = %d\n", recv_buf.size, recv_buf.num);
					break;
				}
				remain_data_size = 1036 - recv_back - remain_data_size;
			}
		}
	}
        因为一直没有对返回值进行判断,这个问题困扰了我好久,,所以再次劝解各位(包括我自己),一定要对函数返回值进行判断。
 

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值