博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TCP明明是报文结构为什么是面向流的?
阅读量:3951 次
发布时间:2019-05-24

本文共 1157 字,大约阅读时间需要 3 分钟。

转载一个知乎的问题:https://www.zhihu.com/question/34003599

TCP是面向字节流的,把数据看做无结构的字节流,但是又有TCP报文段的存在,而且如果看成字节流的话,又是怎么保证数据有序的呢?

而使用java的socket接口的时候,服务器端是直接从输入流中读出字节数据,没有涉及什么报文段,数据乱序的问题,这些东西的关系到底是怎么样的?

法国政府委托人将自由女神按照从上到下,从左到右(类似电视机一帧图像显示方式)的顺序编号,编号为1-300,编号1用1号箱子打包,编号2用2号箱子打包,以此类推,一共300个箱子,快递公司并不关心箱子里装的是啥,在他们眼里这些都是货物,只关心的是如何把这些货物按照法国政府提交的编号顺序(1,2,3…300)运输到目的地,然后按照相同的编号顺序(1,2,3…300)提交给美国政府,任务就算完成了。

至于如何完成以上的任务(乱序、丢包重传)则可以参考以下这个故事。http://www.zhihu.com/question/53960871/answer/137346451

而基于TCP Socket编程,比如客户端使用HTTP请求服务器的主页,服务器生成了自己的主页,一共300K byte数据,包括Header + Payload,为了更清晰说明问题,假设TCP最多一次只能发送1K byte的数据,服务器端程序首先要将300K数据按照顺序砍成300块 (Segment),按照从头到尾编号,1-300,然后调用send()函数300次,严格按照时间顺序,第一次调用发编号1,第二次调用发编号2,…第三百次调用发编号300,这个不复杂,只要编写一个循环程序(300次)即可,只要每次调用的返回值都OK,应用程序的任务就算完成了。

以上的编号1-300就是TCP segment编号,

那字节流的编号呢,就是 1,300000,其中 1-1000 字节被编在1号TCP segment,1001-2000字节编在2号segment,以此类推。TCP不关心本地send()给自己的内容是啥(反正都是字节),只关心时序,先发给自己的肯定先编号,后发的后编号,TCP本身只保证传输的顺序,至于在服务器端本地、客户端本地的顺序则由Receive()/ Send()时序来保证!


问题的关键在于TCP是有缓冲区,作为对比,UDP面向报文段是没有缓冲区的。

TCP发送报文时,是将应用层数据写入TCP缓冲区中,然后由TCP协议来控制发送这里面的数据,而发送的状态是按字节流的方式发送的,跟应用层写下来的报文长度没有任何关系,所以说是流。

作为对比的UDP,它没有缓冲区,应用层写的报文数据会直接加包头交给网络层,由网络层负责分片,所以是面向报文段的。

在这里插入图片描述

你可能感兴趣的文章
OMAP3630 Linux I2C总线驱动分析
查看>>
LDD3 读书笔记之 第 5 章 并发和竞争情况
查看>>
spinlock与linux内核调度的关系
查看>>
Android 显示系统
查看>>
小议C语言中数据的存储类型
查看>>
android双屏显示的一些修改与尝试
查看>>
Android Display System --- Surface Flinger
查看>>
有webservice参与的系统的单元测试, 使用mock object (二)
查看>>
有webservice参与的系统的单元测试, 使用mock object (三)
查看>>
delayed_job 的 基本用法
查看>>
ruby , rspec中测试 module
查看>>
ruby 中的多行字符串(multiple lines of string) %Q, %w, %q
查看>>
linux 中的 photoshop/paintshop: GIMP
查看>>
linux link (ln) 的用法 : ln -s <目标文件> <link_name>
查看>>
多个workers下 delayed_job的问题:
查看>>
capistrano 的几个参数( logger, set-before)
查看>>
对使用开源项目的一点儿讨论
查看>>
ruby中的单元测试
查看>>
python 读写yaml
查看>>
转载: nginx 域名跳转一例~~~(rewrite、proxy)
查看>>