免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 11705 | 回复: 19
打印 上一主题 下一主题

[C] linux下tcp协议的socket可靠传输 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-20 11:21 |只看该作者 |倒序浏览
tcp协议是可靠的,socket只是实现的一种具体方式,并不代表我们使用socket编写的应用程序一定是传输可靠的。
   
  我现在遇到的问题是:
  一个简单的单向上传协议,使用send不停的向tcp server发送数据包,可以理解为一个大文件的上传,由于send、write等函数仅仅是把待发送数据拷贝到发送缓冲区,并不是真正的发送成功,因此,在网络出现瞬时断开时,发送缓冲区中的数据可能无法继续发送成功,但是由于是单向协议,没有服务端的收包确认,应用程序本身也不知道发送缓冲区中还剩余哪些数据没有发送成功,造成实际上的丢包
   
  请问大家,如何确保发送缓冲区中数据成功送达tcp server,而不:
1)修改应用协议
2)降低传输效率
  之所以提到2,是因为我采用
  1.    
  2. int nFixedSndBufSize = 0; struct timeval stTimeval; setsockopt(hSockFD, SOL_SOCKET, SO_SNDBUF, &nFixedSndBufSize, sizeof(int));
复制代码
强制设置发送缓冲为零时,可能能确保成功,但是发送效率急剧下降。

论坛徽章:
2
水瓶座
日期:2013-09-04 15:09:57白羊座
日期:2014-04-17 16:48:13
2 [报告]
发表于 2011-10-20 11:26 |只看该作者
什么意思?

send的返回值不能判断成功与否么?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2011-10-20 11:28 |只看该作者
回复:l2y3n2
不可以,只能代表成功的放置到发送缓冲区中了

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
4 [报告]
发表于 2011-10-20 12:26 |只看该作者
我忘记有没有相应的接口了, 但lz可查询一下有没有可用的发送缓冲的 opt, 配合sndbuf 总大小, 应该可以知道哪些发出去哪些没有了;

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
5 [报告]
发表于 2011-10-20 12:30 |只看该作者
或者不管三七二十一, 直接重复发送断线之前已经send的若干个包, 只要重传的数据大小超过 协议栈 发送buf 的大小, 就能保证不丢包, 让服务器自己排重就可以了

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2011-10-20 15:20 |只看该作者
多谢 zylthinking
在同事和您的双重提醒下,我找到了解决方法:
  1.     size_t ileftUnsend;

  2.         if(ioctl(hSockFD, SIOCOUTQ, (char*)&ileftUnsend) < 0)
  3.         {
  4.                 perror("ioctl SIOCOUTQ error:");
  5.                 return FALSE;
  6.         }else{
  7.                 ... ...
  8.         }
复制代码
要包含头文件:
  1. #include <linux/sockios.h>
复制代码
查询接收缓冲使用:
FIONREAD来替代SIOCOUTQ

再次感谢,也供后来者参考。

论坛徽章:
0
7 [报告]
发表于 2011-10-20 17:57 |只看该作者
我感觉lz你对这个问题理解出现了偏差。TCP协议是可靠传输协议,你投递到SOCKET端口后,自然有TCP协议栈的重传机制保证传输成功,然后会通知SOCKET端口数据传输状态,也就是你需要通过对SOCKET发送后的状态或者其他辅助函数检查数据是否成功,或者到底成功传输出去多少。不是你认为的那样,投递出去我就不管了,也不知到底有否成功了。这个和TCP协议无关,协议自然有他的保证机制,但是面向编程SOCKET它有反馈机制。建议你再仔细研究下异步SOCKET编程。不知道你使用的是什么模型发送数据。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
8 [报告]
发表于 2011-10-20 19:57 |只看该作者
tcp协议是可靠的,socket只是实现的一种具体方式,并不代表我们使用socket编写的应用程序一定是传输可靠的。 ...
notsureit 发表于 2011-10-20 11:21



    最终应该回一个包,表示收到了哪些。

论坛徽章:
0
9 [报告]
发表于 2011-10-20 20:40 |只看该作者
我感觉lz你对这个问题理解出现了偏差。TCP协议是可靠传输协议,你投递到SOCKET端口后,自然有TCP协议栈的重 ...
samzc2010 发表于 2011-10-20 17:57

我想LZ的意思是——当应用进程调用send,并且此时发送缓冲区中有足够大地空间,那么send将把数据发送到该缓冲区中并成功返回。但是此后,可能因为网络中的某些原因致使TCP无法把数据发送到对端,此时应用进程的下层可能会返回消息告诉进程发送失败,但由于send在此之前已经成功返回,所以下层的消息无法正确地传递给应用进程,这就导致了LZ所说的send返回而TCP发送失败吧。不知道我这样理解对不对~~
我是个初学者,看不太懂LZ的解决方法,可否请高手解释一下~~~~

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2011-10-21 09:55 |只看该作者
回复 9# Redshadows


    就是你说的意思,我上面的解决方法就是在程序发现当前网络错误的时候,查询得到当前没有成功发送的位于socket发送缓冲区的数据字节数,由自己的应用程序做后续补发处理,因为后续的措施可能包括断开重连什么的,该缓冲区可能会丢失,为什么说是可能,而不是一定,也和关闭方式有关,不赘述了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP