Tcp拾遗--PSH标志位

注:有勘误!!!

接触网络编程伊始肯定就已涉及tcp。
当然三次握手只是tcp的冰山一脚。

这里为什么提及PSH标志位呢?但凡深究过tcp的数据发送细节,就会了解到tcp报文的数据长度限制。比如:一大块数据的发送会被拆成好几块小报文,至于其它收发中的一些细节不作讨论,此处要讨论的是:tcp发送大块数据时,接收一侧明明是一段一段 one by one地收到的数据,但当你调用recv时怎么就能一下子完整收到呢?(至少java中的tcp实现是这样的,当然你的recv buff需要足够大)。

思来想去必有猫腻,遂起wireshark抓之。

然后发现,在保持tcp链接的情况下,不管发送数据长度大小,最后一次数据发送完成必带PSH标志,且只有最后一次才携带PSH,那原因八成就在于此了。遂查PSH,此文不错可参考之。参考了网上一些博文,tcp/ip那厚厚的几卷实在不想去翻了。从各种博文(比如:上述那篇)大致可以看出:PSH有此层意思–告诉接收端你该赶紧处理这回还有先前收到的数据了。至于PSH其余的作用不作讨论。这就可以解释开头说的现象了。此致。

假如,经tcp发送10000字节数据,接收端调用recv且设置缓冲区10001字节,那就可以一次性获取到所有数据。
至少java环境是这样的,此点应该还是受tcp实现的影响的。
明明这10000个字节会被拆成好几块,而接收时为什么还会有此效果。
原因八成就是:PSH会触发数据被立即交给应用层,哪怕数据还未填满接收缓冲区。

勘误20170405

修正recv数据接收的相关描述。

recv接收数据

1,java中大块数据接收时,并不是一次recv调用就能将所有数据接收到;
2,之前的测试结果--一次性将10000字节全部接收,应该是那种测试情况下的特例。
3,实际接收到的数据一般是:1448的倍数+最后剩余部分。
4,1448是tcp的窗口size,但是大块数据时,这个size会变动,不过会保持1448的倍数。

快捷实现数据接收

InputStream in = null;

        /*保证收到多少返回多少*/
        int ret = 0, sum = 0;
        try {
            sock.setSoTimeout(tmoInMilli);
            in = sock.getInputStream();
            while (true) {
                ret = in.read(buff, sum, buff.length-sum);
                if (ret > 0) {      
//                  System.out.println("got data len:"+ ret);
                    sum += ret;
                }       
                if (ret%1448 != 0) {
                    break;//只有是1448倍数的情况下才会还有数据
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sum;
1,循环接收数据直到出现非1448倍倍数为止。ret:每次返回值,sum:总的接收长度;
2,即便总数据长度正好是1448倍数,无非就是多产生了一次read timeout;
3,产生异常就将异常之前接收的数据返回;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值