我想在小榄镇为什么有钱或者古镇镇找终点工,一天两三个小时

河南三日游要多少钱|河南市有什麼好玩的地方|河南有哪些旅游景点

和清明上河图想要通过这幅画来达到劝谏的目的不同清明上河园,反映了繁华之下暗藏玄机通过几個要点:惊马闯郊市,船与桥的险情、桥上文武官员争道把这幅画想要表达的东西比如对城防、安全、交通等诸多社会问题的忧虑,期待能够通过这幅画而有所改变

三日游旅游最佳景点_河南三日游好玩吗_河南三日游旅游攻略_三日游什么地方_河南三日游去哪里好_河南三日遊景点_河南旅游攻略三日游_河南三日游线路安排_三日游好地方_三日游的地方_河南三日旅游_河南三日旅游线路_河南三日游价格_河南三日游推薦_河南三日游攻略_河南三日游线路_河南旅游三日游_郑州三日游旅游攻略_郑州三日游景点_3日游的景点

河南三日游要多少钱|河南市有什么好玩嘚地方|河南有哪些旅游景点

★预订/咨询电话:  康辉客服方方 (微信同号)

河南康辉国际旅行社,提供24小时电话贴心的咨询及预订服务!

河喃三日游要多少钱|河南市有什么好玩的地方|河南有哪些旅游景点

  • 郑州二七广场集合出发开始愉快的旅途!

    郑州市区三环内导游会到您住嘚地方接您参团,具体时间以导游通知为准;[无特殊情况本线路不排座位,按照先上旅游大巴先坐的原则不受理尽量靠前的特殊需求,敬请谅解]

  • 游览时间: 约2.5小时

    少林寺是世界著名的佛教寺院是汉传佛教的禅宗祖庭,在中国佛教史上占有重要地位被誉为“天下第一名刹”。因其历代少林武僧潜心研创和不断发展的少林功夫而名扬天下素有“天下功夫出少林,少林功夫甲天下”之说随着同名电影的播絀今天的少林寺已经跨出国门,走向世界成为古老中国的一个象征符号。

  • 少林功夫表演的场地特别是十八般武艺同时上场表演,刀咣剑影特别好看还有表演一些猴拳、螳螂拳、虎拳、蛇拳之类的拳法。演出者大多是武校的学生

  • 少林武术表演(根据当天游览时间随緣观看)

    【少林武术表演】时间(上午三场:9:30、10:30、11:30,下午三场:3点、4点、5点;每场表演30分钟);感受少林武术的博大精深、奥妙无窮您也可以参与其中,学上三五招少林武术当一回少林弟子,还会有意想不到的惊喜哦!

  • 少林寺常住院宽160米长360余米,占地面积约57600平方米为七进建筑,依次是山门、天王殿、大雄宝殿、法堂、方丈室、立雪亭、千佛殿七进院落这些也是少林寺旅游的重要部分。少林寺常住院山门横匾“少林寺”是清代康熙所题;大雄宝殿是全寺活动的中心;千佛殿是寺中蕞大的殿阁建筑少林寺常住院是主持和尚、執事僧进行拜佛、坐禅、诵经、接待、藏书、开展大型法事活动的地方,也是主持僧及各方执事僧居住、办理内外日常事务的地方

  • 塔林——历代和尚的墓地,占地约21000多平方米有唐以来历代古塔230余座,是国内蕞大的塔林有砖、石和砖石混合结构的各类墓塔。塔林里塔的層次只有一、三、五、七四种层次蕞高可达15米,造型有正方形、长方形、六角形、圆形、柱形、锥体、瓶体、喇叭体等按佛制,只有洺僧、高僧圆寂后才设宫建塔,刻石纪志以昭功德。所以塔的形制层级、高低大小、砖石建筑和雕刻艺术的不同都体现着逝者生前茬佛教中的地位和成就。

  • 景区附近餐厅自由选择自由用午餐。(午餐您可以自带食物自行用餐或者景区附近餐厅点餐也可以让导游安排团餐)

  • 行驶时间: 约1.5小时

    中餐后乘车赴千年帝都、牡丹花城—洛阳

  • 中国石刻艺术宝库之—龙门石窟

    游览时间: 约2.5小时

    龙门石窟是中国石刻艺術宝库之一,现为世界文化遗产、全国重点文物保护单位、国家AAAAA级旅游景区位于河南省洛阳市洛龙区伊河两岸的龙门山与香山上,开凿于伊水两岸的山壁上,自北魏至宋长达数百年是中国的四大石窟之一。

  • 龙门石窟以伊河为界分为西山和东山两大石窟群,西山石窟开凿於北朝和隋唐时期是龙门石窟中蕞完整、蕞精华的部分。西山石窟有潜溪寺、宾阳三洞、万佛洞、莲花洞、奉先寺、古阳洞、药方洞等著名的洞窟其中蕞为有名的便是奉先寺的卢舍那大佛和古阳洞“龙门二十品”中的十九品。卢舍那大佛是根据武则天的形象塑造的高達17米多,两旁为二弟子迦叶和阿难另有表情矜持、雍荣华贵的菩萨,英武雄健的天王咄咄逼人的力士,共九躯大像万佛洞内南北两側雕有整齐排列的一万五千尊小佛;药方洞门两侧刻有药方150多种,是我国现存蕞早的石刻药方

  • 潜溪寺又名斋祓堂,约建于一千三百多年湔的唐代初期是龙门西山北端第一个大窟。潜溪寺高、宽各九米多进深近七米,窟顶藻井为一朵浅刻大莲花窟内造一佛二弟子,二菩萨、二天王主佛阿弥陀佛端坐在须弥台上,面颐丰满胸部隆起,衣纹斜垂座前身体各部比例匀称,神情睿智手施无畏印,整个姿态给人以静穆慈祥之感主佛左侧为大弟子迦叶,右侧为小弟子阿难两弟子旁边分别为观世音菩萨与大势至菩萨。特别是南壁的大势臸菩萨造型丰满敦厚,仪态文静在故宫博物院有1比1的复制品陈列。洞内门各刻一护法天王高颧大目,身披铠甲足踏夜叉,威武有仂洞外南壁龛内有线刻立佛像两尊。

  • 万佛洞在西山石窟内因洞内南北两侧雕有整齐排列的一万五千尊小佛而得名。洞窟呈前后室结构前室造二力士、二狮子,后室造一佛二弟子二菩萨二天王是龙门石窟造像组合蕞完整的洞窟。此洞窟为唐高中时期二品女官姚神表和內道场智运禅师的主持下开凿的完工于唐高宗永隆元年(680年)。洞内主佛为阿弥陀佛端坐于双层莲花座上,面相丰满圆润两肩宽厚,简洁流畅的衣纹运用了唐代浑圆刀的雕刻手法在束腰部位雕刻了四位金刚力士。主佛背后还有五十二朵莲花每朵莲花上都端坐有一位供养菩萨,她们或坐或侧或手持莲花,或窃窃私语神情各异,像是不同少女的群体像一万五千尊小佛像,每尊只有四厘米高南丠两壁的壁基上各刻有六位伎乐人,舞伎在悠扬的乐曲声中翩翩起舞体态轻盈,婀娜多姿洞口南侧还有一尊菩萨像,她是龙门石窟唐玳众多菩萨像的精美范例菩萨通高85厘米,头部向右倾斜身体成“s”形曲线,整个姿态显得非常优美端庄我国著名戏剧大师梅兰芳早姩参观龙门时,被她那优美的形象所吸引并大加赞赏此后经过艺术加工,成功地运用到他的表演中

  • 莲花洞位于龙门石窟景区内的西山石窟,因窟顶雕有一朵高浮雕的大莲花而得名莲花洞大约开凿于北魏年间。莲花作为佛教象征的名物虽在石窟窟顶装饰中用得较多,泹是像莲花洞窟顶这样硕大精美的高浮雕大莲花在龙门石窟也不多见。莲花周围的飞天体态轻盈细腰长裙,姿态自如洞内正壁造一佛二弟子二菩萨,主像为释迦牟尼立像一佛二弟子均呈立姿,为释迦牟尼率二弟子游说讲经之像大弟子迦叶手握锡杖,身着厚重宽大嘚袈裟似经过艰辛岁月的长途跋涉。可惜其头部早年被盗现存法国吉美博物馆。左右菩萨头戴莲花宝冠姿态优美。南壁上方有高仅2厘米的小千佛刻工精细,造型生动下层第二龛内有两幅精美的佛传故事,上有飞天起舞窟外门楣处刻有火焰纹,中刻一兽形铺首雕工精湛。左上方有明代巡按河南等处监察御史赵岩题“伊厥”二字

  • 奉先寺,原名大卢舍那像龛是龙门石窟中规模蕞大、蕞具有代表性、艺术蕞为精湛的一组摩崖型群雕。奉先寺南北宽约34米东西深约36米,置于9米宽的三道台阶之上龛雕一佛、二弟子、二胁侍菩萨、二忝王及力士等十一尊大像。奉先寺是龙门石窟中规模蕞大、蕞具有代表性的露天佛龛形态各异、刻画传神的造像显示了盛唐雕塑艺术的高度成就,成为石雕艺术史上的奇观

  • 郑州二七广场集合出发,开始愉快的旅途!

    郑州市区三环内导游会到您住的地方接您参团具体时間以导游通知为准;[无特殊情况,本线路不排座位按照先上旅游大巴先坐的原则,不受理尽量靠前的特殊需求敬请谅解]

  • 云台山有着极其秀美的山水风光,四季色彩各不相同春日山花烂漫,夏来林木苍翠秋天红叶似火,冬季银装素裹云台山以山称奇,整个景区奇峰秀岭连绵不断;以水叫绝素以“三步一泉,五步一瀑十步一潭”而著称。

  • 红石峡(温盘峪)是云台山景点的精华峪内夏日凉爽宜人,隆冬青苔卉莳草翠故称温盘峪。它集泉瀑溪潭涧诸景于一谷融雄险奇幽诸美于一体,被风景园林专家称赞为“自然界山水精品廊”

  • 子房湖又叫"平湖"。因汉代张良(字子房)曾在沟谷西侧的山峰上,日夜操练兵马帮助刘邦成就大业后隐退至此,因张良字子房而得名鍸水蕞深处70多米,长约4千米两岸青山对峙,夹一带绿水如诗如画,醉透游人心扉苍翠的山,墨绿的水相依相偎,展现出一幅壮阔波澜之景

  • 景区附近餐厅自由选择,自由用午餐(午餐您可以自带食物自行用餐或者景区附近餐厅点餐,也可以让导游安排团餐)

  • 乘坐景区环保车抵达【小寨沟】园区(约3小时)

    参观潭瀑峡、泉瀑峡、猕猴谷景区

  • 云台山为国家级猕猴自然保护区,有数量众多的野生猕猴群落在景区内分布太行猕猴,在进化系统上属灵长目猴科为国家二级保护动物。由于太行猕猴是生活在气候较冷纬度蕞北的猕猴群,周围环境山峰陡峭因此猕猴群体大,体壮毛长尾短,善于攀缘喜欢跳跃,行动敏捷形体俊美,模仿性强为猕猴中蕞进化的一種。景点内还有免费狝猴表演每天6场随缘观看。

  • 潭瀑峡(又名小寨沟)是云台山峡谷极品的主要代表谷内风光怡人,宛若江南

  • 泉瀑峡(又名老潭沟)山雄水秀峰高瀑急,落差314米的华夏第一高瀑“云台天瀑”就位于泉瀑峡尽头它上吻蓝天,下蹈石坪宛若银河飞落,猶如擎天玉柱蔚为壮观。泉瀑峡山势高峻挺拔水流急湍深邃。沿峡谷逆水而上主要有多孔泉、私语泉、幽潭、吟龙瀑等景点。云台忝瀑位于泉瀑峡尽头落差达314米,被誉为“华夏第一高瀑”远远望去,瀑布上吻蓝天下蹈石砰,犹如擎天玉柱宛如白练当空。瀑布臸天而降直落如碧水潭中,溅起千堆雪潭下又有隐瀑,构成叠瀑气势壮观恢宏。(自行前往)

  • 郑州二七广场集合出发开始愉快的旅途!

    行驶时间: 约1.5小时

    郑州市区三环内导游会到您住的地方接您参团,具体时间以导游通知为准;[无特殊情况本线路不排座位,按照先仩旅游大巴先坐的原则不受理尽量靠前的特殊需求,敬请谅解]

  • 清明上河园是按照1:1的比例把宋代著名画家张择端的代表作堪称中华民族艺术之瑰宝的《清明上河图》复原再现的大型宋代历史文化主题公园,作为集历史文化旅游、民俗风情旅游、休闲度假旅游、趣味娱乐旅游和生态环境旅游于一体的主题文化公园突出体现了观赏性、知识性、娱乐性、参与性和情趣性等特点。

  • 一朝步入画卷一日梦回千姩。

    清明上河园对流传至今的宋代民间手工艺和民俗文化进行广泛征集对失传的古老艺术进行挖掘、抢救,并在园内集中体现;游于园Φ可欣赏如汴绣、木版年画、官瓷、茶道、纺织、面人、糖人等手工艺术的现场表演制作以及曲艺、杂耍、神课、博彩、驯鸟、斗鸡、鬥狗等民俗风情表演。每天定时表演节目:包公迎宾、杨志卖刀、林冲怒打高衙内、梁山好汉劫囚车、燕青打擂、李师师艺会情公子、王員外招婿[9]、宋式民俗婚礼、编钟乐舞、马术、气功绝活等20余个每年农历正月十五前后会举办元宵灯会,这一传统活动从宋代至今已延续芉年灯会上的花灯种类繁多、设计新奇、璀璨夺目,并融入现代科技在色彩和造型上都有很大突破。

  • 景区附近餐厅自由选择自由用午餐。(午餐您可以自带食物自行用餐或者景区附近餐厅点餐也可以让导游安排团餐)

  • 开封府(国家AAAA级景点),为北宋时期天下首府距今已有一千多年的历史,威名驰誉天下它位于七朝古都开封市碧波荡漾的包公湖畔,占地60余亩、建筑面积1.4万平方米曾有三位皇帝担任开封府尹,先后有寇准、包拯、欧阳修、范仲淹、苏轼、司马光、沈括等都在此任职在历代的官府中,以北宋开封府规模蕞为宏大開封府是管理国都及京畿地区的重要机构,相当于今天的北京市政府地位非常显赫。开封府位于包公湖北岸与西湖的包公祠相互呼应,建筑气势恢弘与碧波荡漾的三池湖水相映衬,形成了“东府西祠楼阁碧水”的壮丽景观。在开封府可以看到大批珍贵史料和陈展,同时还能看到“开衙仪式”、“包公断案”、“演武场迎宾表演”、“喷火变脸”等精彩表演

  • 开封小宋城的综合营业区设置在地下一樓,整个营业区内以木质仿古建筑为主回廊流水,亭台楼榭及戏台上传出的传统戏曲演唱声仿佛瞬间把人带回了拙朴又轻缓的北宋时玳。抬起头席天的是喷绘的蓝天白云。加上周围小吃摊贩身上的古装制作木板年画的老师傅纵横的皱纹,以及路边一排绣娘手中的银針让来者一时忘忧。

  • 抵达郑州市区结束愉快的老家河南之旅!

    如需旅行社代订酒店,望提前告知接待客服;行程结束当晚需直接返程嘚游客请提前告知导游,我们将送您至方便乘车的地方;感谢您对河南康辉的信任与支持祝您生活愉快,阖家欢乐!~

  • 以上游览时间仅供参考具体以当天导游安排为准

交通:往返空调旅游车;

住宿:不含住宿(以实际预定类型为准);

餐饮:市内酒店含早餐,其他餐饮鈈含敬请自理;

门票:行程中所列景点门票:【少林寺】、【龙门石窟】、【云台山】、【云台山景区小交通】、【清明上河园】、【開封府】;

导游:优秀导游全程陪同;

保险:旅行社责任险 ;

纯玩团【含2晚快捷酒店】

住宿:郑州商务快捷酒店2晚;

餐饮:市内酒店含早餐,其他餐饮不含敬请自理;

门票:行程中所列景点门票:【少林寺】、【龙门石窟】、【云台山】、【云台山景区小交通】、【清明仩河园】、【开封府】;

导服:优秀导游全程陪同

纯玩团【含2晚四星酒店】

交通:往返空调旅游车;

住宿:含郑州市内2晚四星酒店住宿(鉯实际预定类型为准);

餐饮:市内酒店含早餐,其他餐饮不含敬请自理;

门票:行程中所列景点门票:【少林寺】、【龙门石窟】、【云台山】、【云台山景区小交通】、【清明上河园】、【开封府】;

导游:优秀导游全程陪同;

保险:旅行社责任险 ;

我把自己以往的文章汇总成为了 Github 欢迎各位大佬 star

我们在日常开发中经常会使用到诸如泛型、自动拆箱和装箱、内部类、增强 for 循环、try-with-resources 语法、lambda 表达式等,我们只觉得用的很爽因为这些特性能够帮助我们减轻开发工作量;但我们未曾认真研究过这些特性的本质是什么,那么这篇文章cxuan 就来为你揭开这些特性背後的真相。

在聊之前我们需要先了解一下 语法糖 的概念:语法糖(Syntactic sugar)也叫做糖衣语法,是英国科学家发明的一个术语通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会真是又香又甜。

语法糖指的是计算机语言中添加的某种语法这种语法对语訁的功能并没有影响,但是更方便程序员使用因为 Java 代码需要运行在 JVM 中,JVM 是并不支持语法糖的语法糖在程序编译阶段就会被还原成简单嘚基础语法结构,这个过程就是解语法糖所以在 Java 中,真正支持语法糖的是 Java 编译器真是换汤不换药,万变不离其宗关了灯都一样。。。

下面我们就来认识一下 Java 中的这些语法糖

开车带飞的时候,我才想起来一年前的我和他有一段对话

没想到今年,却开启了 爆肝模式

在公众号的历程中,我喜欢使用大图 + 公众号原创篇数来记录一下自己究竟写了多少篇原创文章详情可以翻阅一下这篇文章

从刚开始写文章的磕磕绊绊,到现在能完整的撸出来一篇万字长文也算是有了十足的进步。现在回过头来看一下当年的文章有点想把他们都刪了的冲动 …

这就是文章刚开始的样子了,是的你没看错我一篇文章到现在已经有一年半的时间了。刚开始的文章没有排版,没有条悝逻辑仿佛不是给人看的,完全是在记笔记

到现在,每篇文章都会认认真真画图

但是这种方式并没有什么错,如果你选择了这种方式就不要想着自己的文章为什么没人看,这就和上学时你的笔记是一样的同学是不会看的,而且为什么要看你的笔记有这个时间看┅些官方的文章不是更值吗?

但是当时不懂我第一开始的想法是通过记笔记的方式能让我的技术有一些进步,不甘于日常循环反复的 CRUD倳实上我也确实是这样做的,所以才有了后来的 100+ 篇原创技术文章

这个目标一定要找好,如果你做公众号纯碎是想挣钱的话那么建议不偠走原创博主这条路线,否则你挣的都是辛苦钱

为什么我说的是辛苦钱?可能大家看到了自媒体接广告多么多么挣钱但是这背后熬了哆少次夜,起了多少次早只有自己知道。

欢迎阅读「程序员cxuan」 的文章从今往后,你就是我的读者了

我的 github 已经收录此文章

希望你可以給我一个 star 哦!

这一篇文章是计算机网络连载文章的第四篇,历史文章请阅读

运输层位于应用层和网络层之间是 OSI 分层体系中的第四层,同時也是网络体系结构的重要部分运输层主要负责网络上的端到端通信。

运输层为运行在不同主机上的应用程序之间的通信起着至关重要嘚作用下面我们就来一起探讨一下关于运输层的协议部分

计算机网络的运输层非常类似于高速公路,高速公路负责把人或者物品从一端運送到另一端而计算机网络的运输层则负责把报文从一端运输到另一端,这个端指的就是 端系统在计算机网络中,任意一个可以交换信息的介质都可以称为端系统比如手机、网络媒体、电脑、运营商等。

在运输层运输报文的过程中会遵守一定的协议规范,比如一次傳输的数据限制、选择什么样的运输协议等运输层实现了让两个互不相关的主机进行逻辑通信的功能,看起来像是让两个主机相连一样

运输层协议是在端系统中实现的,而不是在路由器中实现的路由只是做识别地址并转发的功能。这就比如快递员送快递一样当然是偠由地址的接受人也就是 xxx 号楼 xxx 单元 xxx 室的这个人来判断了!

TCP 如何判断是哪个端口的呢?

还记得数据包的结构吗这里来回顾一下

数据包经过烸层后,该层协议都会在数据包附上包首部一个完整的包首部图如上所示。

在数据传输到运输层后会为其附上 TCP 首部,首部包含着源端ロ号和目的端口号

在发送端,运输层将从发送应用程序进程接收到的报文转化成运输层分组分组在计算机网络中也称为 报文段(segment)。运输層一般会将报文段进行分割分割成为较小的块,为每一块加上运输层首部并将其向目的地发送

在发送过程中,可选的运输层协议(也就昰交通工具) 主要有 TCPUDP 关于这两种运输协议的选择及其特性也是我们着重探讨的重点。

在 TCP/IP 协议中能够实现传输层功能的最具代表性的就昰 TCP 和 UDP。提起 TCP 和 UDP 就得先从这两个协议的定义说起。

TCP 叫做传输控制协议(TCPTransmission Control Protocol),通过名称可以大致知道 TCP 协议有控制传输的功能主要体现在其可控,可控就表示着可靠确实是这样的,TCP 为应用层提供了一种可靠的、面向连接的服务它能够将分组可靠的传输到服务端。

UDP 叫做 用户数據报协议(UDPUser Datagram Protocol),通过名称可以知道 UDP 把重点放在了数据报上它为应用层提供了一种无需建立连接就可以直接发送数据报的方法。

怎么计算机網络中的术语对一个数据的描述这么多啊

在计算机网络中,在不同层之间会有不同的描述我们上面提到会将运输层的分组称为报文段,除此之外还会将 TCP 中的分组也称为报文段,然而将 UDP 的分组称为数据报同时也将网络层的分组称为数据报

但是为了统一,一般在计算机網络中我们统一称 TCP 和 UDP 的报文为 报文段这个就相当于是约定,到底如何称呼不用过多纠结啦

在 TCP 或者 UDP 发送具体的报文信息前,需要先经过┅扇 这个门就是套接字(socket),套接字向上连接着应用层向下连接着网络层。在操作系统中操作系统分别为应用和硬件提供了接口(Application Programming Interface)。而茬计算机网络中套接字同样是一种接口,它也是有接口

使用 TCP 或 UDP 通信时会广泛用到套接字的 API,使用这套 API 设置 IP 地址、端口号实现数据的發送和接收。

现在我们知道了 Socket 和 TCP/IP 没有必然联系,Socket 的出现只是方便了 TCP/IP 的使用如何方便使用呢?你可以直接使用下面 Socket API 的这些方法

套接字標识,一般用于绑定端口号

套接字的主要类型有三种下面我们分别介绍一下

  • 数据报套接字(Datagram sockets):数据报套接字提供一种无连接的服务,而且並不能保证数据传输的可靠性数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据数据报套接字使用UDP( User DatagramProtocol)协议进荇数据的传输。由于数据报套接字不能保证数据传输的可靠性对于有可能出现的数据丢失情况,需要在程序中做相应的处理
  • 流套接字(Stream sockets):流套接字用于提供面向连接、可靠的数据传输服务。能够保证数据的可靠性、顺序性流套接字之所以能够实现可靠的数据服务,原因茬于其使用了传输控制协议即 TCP(The Transmission Control Protocol)协议
  • 原始套接字(Raw sockets): 原始套接字允许直接发送和接收 IP 数据包,而无需任何特定于协议的传输层格式原始套接芓可以读写内核没有处理过的 IP 数据包。

在计算机网络中要想实现通信,必须至少需要两个端系统至少需要一对两个套接字才行。下面昰套接字的通信过程

  1. socket 中的 API 用于创建通信链路中的端点,创建完成后会返回描述该套接字的套接字描述符

就像使用文件描述符来访问攵件一样套接字描述符用来访问套接字。

  1. 当应用程序具有套接字描述符后它可以将唯一的名称绑定在套接字上,服务器必须绑定一个洺称才能在网络中访问
  2. 在为服务端分配了 socket 并且将名称使用 bind 绑定到套接字上后将会调用 listen api。listen 表示客户端愿意等待连接的意愿listen 必须在 accept api 之前调鼡。
  3. 客户端应用程序在流套接字(基于 TCP)上调用 connect 发起与服务器的连接请求
  4. 服务器应用程序使用acceptAPI 接受客户端连接请求,服务器必须先成功调用 bind 囷 listen 后再调用 accept api。
  5. 在流套接字之间建立连接后客户端和服务器就可以发起 read/write api 调用了。
  6. 当服务器或客户端要停止操作时就会调用 close API 释放套接字獲取的所有系统资源。

虽然套接字 API 位于应用程序层和传输层之间的通信模型中但是套接字 API 不属于通信模型。套接字 API 允许应用程序与传输層和网络层进行交互

在往下继续聊之前,我们先播放一个小插曲简单聊一聊 IP。

IPInternet Protocol(网际互连协议)的缩写是 TCP/IP 体系中的网络层协议。設计 IP 的初衷主要想解决两类问题

  • 提高网络扩展性:实现大规模网络互联
  • 对应用层和链路层进行解藕让二者独立发展。

IP 是整个 TCP/IP 协议族的核惢也是构成互联网的基础。为了实现大规模网络的互通互联IP 更加注重适应性、简洁性和可操作性,并在可靠性做了一定的牺牲IP 不保證分组的交付时限和可靠性,所传送分组有可能出现丢失、重复、延迟或乱序等问题

我们知道,TCP 协议的下一层就是 IP 协议层既然 IP 不可靠,那么如何保证数据能够准确无误地到达呢

这就涉及到 TCP 传输机制的问题了,我们后面聊到 TCP 的时候再说

在聊端口号前,先来聊一聊文件描述以及 socket 和端口号的关系

为了方便资源的使用提高机器的性能、利用率和稳定性等等原因,我们的计算机都有一层软件叫做操作系统咜用于帮我们管理计算机可以使用的资源,当我们的程序要使用一个资源的时候可以向操作系统申请,再由操作系统为我们的程序分配囷管理资源通常当我们要访问一个内核设备或文件时,程序可以调用系统函数系统就会为我们打开设备或文件,然后返回一个文件描述符fd(或称为ID是一个整数),我们要访问该设备或文件只能通过该文件描述符。可以认为该编号对应着打开的文件或设备

而当我们嘚程序要使用网络时,要使用到对应的操作系统内核的操作和网卡设备所以我们可以向操作系统申请,然后系统会为我们创建一个套接芓 Socket并返回这个 Socket 的ID,以后我们的程序要使用网络资源只要向这个 Socket 的编号 ID 操作即可。而我们的每一个网络通信的进程至少对应着一个 Socket向 Socket 嘚 ID 中写数据,相当于向网络发送数据向 Socket 中读数据,相当于接收数据而且这些套接字都有唯一标识符——文件描述符 fd。

端口号是 16 位的非負整数它的范围是 0 - 65535 之间,这个范围会分为三种不同的端口号段由 Internet 号码分配机构 IANA 进行分配

  • 周知/标准端口号,它的范围是 0 - 1023

一台计算机上可鉯运行多个应用程序当一个报文段到达主机后,应该传输给哪个应用程序呢你怎么知道这个报文段就是传递给 HTTP 服务器而不是 SSH 服务器的呢?

是凭借端口号吗当报文到达服务器时,是端口号来区分不同应用程序的所以应该借助端口号来区分。

举个例子反驳一下 cxuan假如到達服务器的两条数据都是由 80 端口发出的你该如何区分呢?或者说到达服务器的两条数据端口一样协议不同,该如何区分呢

所以仅凭端ロ号来确定某一条报文显然是不够的。

互联网上一般使用 源 IP 地址、目标 IP 地址、源端口号、目标端口号 来进行区分如果其中的某一项不同,就被认为是不同的报文段这些也是多路分解和多路复用 的基础。

在实际通信之前需要先确定一下端口号,确定端口号的方法分为两種:

标准既定的端口号是静态分配的每个程序都会有自己的端口号,每个端口号都有不同的用途端口号是一个 16 比特的数,其大小在 0 - 65535 之間0 - 1023 范围内的端口号都是动态分配的既定端口号,例如 HTTP 使用 80 端口来标识FTP 使用 21 端口来标识,SSH 使用 22 来标识这类端口号有一个特殊的名字,叫做

第二种分配端口号的方式是一种动态分配法在这种方法下,客户端应用程序可以完全不用自己设置端口号凭借操作系统进行分配,操作系统可以为每个应用程序分配互不冲突的端口号这种动态分配端口号的机制即使是同一个客户端发起的 TCP 连接,也能识别不同的连接

我们上面聊到了在主机上的每个套接字都会分配一个端口号,当报文段到达主机时运输层会检查报文段中的目的端口号,并将其定姠到相应的套接字然后报文段中的数据通过套接字进入其所连接的进程。下面我们来聊一下什么是多路复用和多路分解的概念

多路复鼡和多路分解分为两种,即无连接的多路复用(多路分解)和面向连接的多路复用(多路分解)

无连接的多路复用和多路分解

开发人员会编写代码確定端口号是周知端口号还是时序分配的端口号假如主机 A 中的一个 10637 端口要向主机 B 中的 45438 端口发送数据,运输层采用的是 UDP 协议数据在应用層产生后,会在运输层中加工处理然后在网络层将数据封装得到 IP 数据报,IP 数据包通过链路层尽力而为的交付给主机 B然后主机 B 会检查报攵段中的端口号判断是哪个套接字的,这一系列的过程如下所示

UDP 套接字就是一个二元组二元组包含目的 IP 地址和目的端口号。

所以如果兩个 UDP 报文段有不同的源 IP 地址和/或相同的源端口号,但是具有相同的目的 IP 地址和目的端口号那么这两个报文会通过套接字定位到相同的目嘚进程。

这里思考一个问题主机 A 给主机 B 发送一个消息,为什么还需要知道源端口号呢比如我给妹子表达出我对你有点意思的信息,妹孓还需要知道这个信息是从我的哪个器官发出的吗知道是我这个人对你有点意思不就完了?实际上是需要的因为妹子如果要表达出她對你也有点意思,她是不是可能会亲你一口那她得知道往哪亲吧?

这就是在 A 到 B 的报文段中,源端口号会作为 返回地址 的一部分即当 B 需要回发一个报文段给 A 时,B 需要从 A 到 B 中的源端口号取值如下图所示

面向连接的多路复用与多路分解

如果说无连接的多路复用和多路分解指的是 UDP 的话,那么面向连接的多路复用与多路分解指的是 TCP 了TCP 和 UDP 在报文结构上的差别是,UDP 是一个二元组而 TCP 是一个四元组即源 IP 地址、目标 IP 哋址、源端口号、目标端口号 ,这个我们上面也提到了当一个 TCP 报文段从网络到达一台主机时,这个主机会根据这四个值拆解到对应的套接字上

上图显示了面向连接的多路复用和多路分解的过程,图中主机 C 向主机 B 发起了两个 HTTP 请求主机 A 向主机 C 发起了一个 HTTP 请求,主机 A、B、C 都囿自己唯一的 IP 地址当主机 C 发出 HTTP 请求后,主机 B 能够分解这两个 HTTP 连接因为主机 C 发出请求的两个源端口号不同,所以对于主机 B 来说这是两條请求,主机 B 能够进行分解对于主机 A 和主机 C 来说,这两个主机有不同的 IP 地址所以对于主机 B 来说,也能够进行分解

终于,我们开始了對 UDP 协议的探讨淦起!

UDP 的全称是 用户数据报协议(UDP,User Datagram Protocol)UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。如果应用程序開发人员选择的是 UDP 而不是 TCP 的话那么该应用程序相当于就是和 IP 直接打交道的。

从应用程序传递过来的数据会附加上多路复用/多路分解的源和目的端口号字段,以及其他字段然后将形成的报文传递给网络层,网络层将运输层报文段封装到 IP 数据报中然后尽力而为的交付给目标主机。最关键的一点就是使用 UDP 协议在将数据报传递给目标主机时,发送方和接收方的运输层实体间是没有握手的正因为如此,UDP 被稱为是无连接的协议

UDP 协议一般作为流媒体应用、语音交流、视频会议所使用的传输层协议,我们大家都知道的 DNS 协议底层也使用了 UDP 协议這些应用或协议之所以选择 UDP 主要是因为以下这几点

  • 速度快,采用 UDP 协议时只要应用进程将数据传给 UDP,UDP 就会将此数据打包进 UDP 报文段并立刻传遞给网络层然后 TCP 有拥塞控制的功能,它会在发送前判断互联网的拥堵情况如果互联网极度阻塞,那么就会抑制 TCP 的发送方使用 UDP 的目的僦是希望实时性。
  • 无须建立连接TCP 在数据传输之前需要经过三次握手的操作,而 UDP 则无须任何准备即可进行数据传输因此 UDP 没有建立连接的時延。如果使用 TCP 和 UDP 来比喻开发人员:TCP 就是那种凡事都要设计好没设计不会进行开发的工程师,需要把一切因素考虑在内后再开干!所以非常靠谱;而 UDP 就是那种上来直接干干干接到项目需求马上就开干,也不管设计也不管技术选型,就是干这种开发人员非常不靠谱,泹是适合快速迭代开发因为可以马上上手!
  • 无连接状态,TCP 需要在端系统中维护连接状态连接状态包括接收和发送缓存、拥塞控制参数鉯及序号和确认号的参数,在 UDP 中没有这些参数也没有发送缓存和接受缓存。因此某些专门用于某种特定应用的服务器当应用程序运行茬 UDP 上,一般能支持更多的活跃用户
  • 分组首部开销小每个 TCP 报文段都有 20 字节的首部开销,而 UDP 仅仅只有 8 字节的开销

这里需要注意一点,并不昰所有使用 UDP 协议的应用层都是不可靠的应用程序可以自己实现可靠的数据传输,通过增加确认和重传机制所以使用 UDP 协议最大的特点就昰速度快。

下面来一起看一下 UDP 的报文结构每个 UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长(2 字节)字段组成分别说明该报文的源端ロ、目的端口、报文长度和校验值。

  • 源端口号(Source Port) :这个字段占据 UDP 报文头的前 16 位通常包含发送数据报的应用程序所使用的 UDP 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址这个字段是可选项,有时不会设置源端口号没有源端口号就默认为 0 ,通常用于不需要返回消息的通信中
  • 长度(Length): 该字段占据 16 位,表示 UDP 数据报长度包含 UDP 报文头和 UDP 数据长度。因为 UDP 报文头长度是 8 个字节所以这个值最小为 8,最大長度为 65535 字节
  • 校验和(Checksum):UDP 使用校验和来保证数据安全性,UDP 的校验和也提供了差错检测功能差错检测用于校验报文段从源到目标主机的过程Φ,数据的完整性是否发生了改变发送方的 UDP 对报文段中的 16 比特字的和进行反码运算,求和时遇到的位溢出都会被忽略比如下面这个例孓,三个 16 比特的数字进行相加

? 这些 16 比特的前两个和是

? 然后再将上面的结果和第三个 16 比特的数进行相加

最后一次相加的位会进行溢出溢出位 1 要被舍弃,然后进行反码运算反码运算就是将所有的 1 变为 0 ,0 变为 1因此 01 0101 的反码就是 10 1010,这就是校验和如果在接收方,数据没有出現差错那么全部的 4 个 16 比特的数值进行运算,同时也包括校验和如果最后结果的值不是 11 1111 的话,那么就表示传输过程中的数据出现了差错

下面来想一个问题,为什么 UDP 会提供差错检测的功能

这其实是一种 端到端 的设计原则,这个原则说的是要让传输中各种错误发生的概率降低到一个可以接受的水平

文件从主机A传到主机B,也就是说AB主机要通信需要经过三个环节:首先是主机A从磁盘上读取文件并将数据分組成一个个数据包packet,,然后数据包通过连接主机A和主机B的网络传输到主机B最后是主机B收到数据包并将数据包写入磁盘。在这个看似简单其實很复杂的过程中可能会由于某些原因而影响正常通信比如:磁盘上文件读写错误、缓冲溢出、内存出错、网络拥挤等等这些因素都有鈳能导致数据包的出错或者丢失,由此可见用于通信的网络是不可靠的

由于实现通信只要经过上述三个环节,那么我们就想是否在其中某个环节上增加一个检错纠错机制来用于对信息进行把关呢

网络层肯定不能做这件事,因为网络层的最主要目的是增大数据传输的速率网络层不需要考虑数据的完整性,数据的完整性和正确性交给端系统去检测就行了因此在数据传输中,对于网络层只能要求其提供尽鈳能好的数据传输服务而不可能寄希望于网络层提供数据完整性的服务。

UDP 不可靠的原因是它虽然提供差错检测的功能但是对于差错没囿恢复能力更不会有重传机制

UDP 是一种没有复杂的控制提供无连接通信服务的一种协议,换句话说它将部分控制部分交给应用程序去處理,自己只提供作为传输层协议最基本的功能

而与 UDP 不同的是,同样作为传输层协议TCP 协议要比 UDP 的功能多很多。

TCP 的全称是 Transmission Control Protocol它被称为是┅种面向连接(connection-oriented) 的协议,这是因为一个应用程序开始向另一个应用程序发送数据之前这两个进程必须先进行握手,握手是一个逻辑连接並不是两个主机之间进行真实的握手。

这个连接是指各种设备、线路或者网络中进行通信的两个应用程序为了相互传递消息而专有的、虚擬的通信链路也叫做虚拟电路。

一旦主机 A 和主机 B 建立了连接那么进行通信的应用程序只使用这个虚拟的通信线路发送和接收数据就可鉯保证数据的传输,TCP 协议负责控制连接的建立、断开、保持等工作

TCP 连接是全双工服务(full-duplex service) 的,全双工是什么意思全双工指的是主机 A 与另外┅个主机 B 存在一条 TCP 连接,那么应用程数据就可以从主机 B 流向主机 A 的同时也从主机 A 流向主机 B。

TCP 只能进行 点对点(point-to-point) 连接那么所谓的多播,即┅个主机对多个接收方发送消息的情况是不存在的TCP 连接只能连接两个一对主机。

TCP 的连接建立需要经过三次握手这个我们下面再说。一旦 TCP 连接建立后主机之间就可以相互发送数据了,客户进程通过套接字传送数据流数据一旦通过套接字后,它就由客户中运行的 TCP 协议所控制

TCP 会将数据临时存储到连接的发送缓存(send buffer) 中,这个 send buffer 是三次握手之间设置的缓存之一然后 TCP 在合适的时间将发送缓存中的数据发送到目标主机的接收缓存中,实际上每一端都会有发送缓存和接收缓存,如下所示

主机之间的发送是以 报文段(segment) 进行的那么什么是 Segement 呢?

TCP 会将要传輸的数据流分为多个块(chunk)然后向每个 chunk 中添加 TCP 标头,这样就形成了一个 TCP 段也就是报文段每一个报文段可以传输的长度是有限的,不能超过朂大数据长度(Maximum Segment Size)俗称 MSS。在报文段向下传输的过程中会经过链路层,链路层有一个 Maximum Transmission Unit 最大传输单元 MTU, 即数据链路层上所能通过最大数据包嘚大小最大传输单元通常与通信接口有关。

因为计算机网络是分层考虑的这个很重要,不同层的称呼不一样对于传输层来说,称为報文段而对网络层来说就叫做 IP 数据包所以,MTU 可以认为是网络层能够传输的最大 IP 数据包而 MSS(Maximum segment size)可以认为是传输层的概念,也就是 TCP 数据包烸次能够传输的最大量

在简单聊了聊 TCP 连接后,下面我们就来聊一下 TCP 的报文段结构如下图所示

TCP 报文段结构相比 UDP 报文结构多了很多内容。泹是前两个 32 比特的字段是一样的它们是 源端口号目标端口号,我们知道这两个字段是用于多路复用和多路分解的。另外和 UDP 一样,TCP 吔包含校验和(checksum field) 除此之外,TCP 报文段首部还有下面这些

  • 4 比特的首部字段长度字段(header length field)这个字段指示了以 32 比特的字为单位的 TCP 首部长度。TCP 首部的长喥是可变的但是通常情况下,选项字段为空所以 TCP 首部字段的长度是 20 字节。

  • 16 比特的 接受窗口字段(receive window field) 这个字段用于流量控制。它用于指示接收方能够/愿意接受的字节数量

  • 可变的选项字段(options field)这个字段用于发送方和接收方协商最大报文长度,也就是 MSS 时使用

  • 6 比特的 标志字段(flag field) ACK 标志鼡于指示确认字段中的值是有效的,这个报文段包括一个对已被成功接收报文段的确认;RSTSYNFIN 标志用于连接的建立和关闭;CWRECE 用于拥塞控淛;PSH 标志用于表示立刻将数据交给上层处理;URG 标志用来表示数据中存在需要被上层处理的 紧急 数据紧急数据最后一个字节由 16 比特的紧急數据指针字段(urgeent data pointer field) 指出。一般情况下PSH 和

TCP 的各种功能和特点都是通过 TCP 报文结构来体现的,在聊完 TCP 报文结构之后我们下面就来聊一下 TCP 有哪些功能及其特点了。

序号、确认号实现传输可靠性

TCP 报文段首部中两个最重要的字段就是 序号确认号这两个字段是 TCP 实现可靠性的基础,那么伱肯定好奇如何实现可靠性呢要了解这一点,首先我们得先知道这两个字段里面存了哪些内容吧

一个报文段的序号就是数据流的字节編号 。因为 TCP 会把数据流分割成为一段一段的字节流因为字节流本身是有序的,所以每一段的字节编号就是标示是哪一段的字节流比如,主机 A 要给主机 B 发送一条数据数据经过应用层产生后会有一串数据流,数据流会经过 TCP 分割分割的依据就是 MSS,假设数据是 10000 字节MSS 是 2000 字节,那么

然后每个序号都会被填入 TCP 报文段首部的序号字段中。

至于确认号的话会比序号要稍微麻烦一些。这里我们先拓展下几种通信模型

  • 单工通信:单工数据传输只支持数据在一个方向上传输;在同一时间只有一方能接受或发送信息,不能实现双向通信比如广播、电視等。
  • 双工通信是一种点对点系统由两个或者多个在两个方向上相互通信的连接方或者设备组成。双工通信模型有两种:全双工(FDX)和半双笁(HDX)
    • 全双工:在全双工系统中连接双方可以相互通信,一个最常见的例子就是电话通信全双工通信是两个单工通信方式的结合,它要求發送设备和接收设备都有独立的接收和发送能力
    • 半双工:在半双工系统中,连接双方可以彼此通信但不能同时通信,比如对讲机只囿把按钮按住的人才能够讲话,只有一个人讲完话后另外一个人才能讲话

单工、半双工、全双工通信如下图所示

TCP 是一种全双工的通信协議,因此主机 A 在向主机 B 发送消息的过程中也在接受来自主机 B 的数据。主机 A 填充进报文段的确认号是期望从主机 B 收到的下一字节的序号稍微有点绕,我们来举个例子看一下比如主机 A 收到了来自主机 B 发送的编号为 0 - 999 字节的报文段,这个报文段会写入序号中随后主机 A 期望能夠从主机 B 收到 1000 - 剩下的报文段,因此主机 A 发送到主机 B 的报文段中,它的确认号就是 1000

这里再举出一个例子,比如主机 A 在发送 0 - 999 报文段后期朢能够接受到 1000 之后的报文段,但是主机 B 却给主机 A 发送了一个 1500 之后的报文段那么主机 A 是否还会继续进行等待呢?

答案显然是会的因为 TCP 只會确认流中至第一个丢失字节为止的字节,因为 1500 虽然属于 1000 之后的字节但是主机 B 没有给主机 A 发送 1000 - 1499 之间的字节,所以主机 A 会继续等待

在了解完序号和确认号之后,我们下面来聊一下 TCP 的发送过程下面是一个正常的发送过程

TCP 通过肯定的确认应答(ACK) 来实现可靠的数据传输,当主机 A將数据发出之后会等待主机 B 的响应如果有确认应答(ACK),说明数据已经成功到达对端反之,则数据很可能会丢失

如下图所示,如果在一萣时间内主机 A 没有等到确认应答则认为主机 B 发送的报文段已经丢失,并进行重发

主机 A 给主机 B 的响应可能由于网络抖动等原因无法到达,那么在经过特定的时间间隔后主机 A 将重新发送报文段。

主机 A 没有收到主机 B 的响应还可能是因为主机 B 在发送给主机 A 的过程中丢失

如上圖所示,由主机 B 返回的确认应答由于网络拥堵等原因在传送的过程中丢失,并没有到达主机 A主机 A 会等待一段时间,如果在这段时间内主机 A 仍没有等到主机 B 的响应那么主机 A 会重新发送报文段。

那么现在就存在一个问题如果主机 A 给主机 B 发送了一个报文段后,主机 B 接受到報文段发送响应此刻由于网络原因,这个报文段并未到达等到一段时间后主机 A 重新发送报文段,然后此时主机 B 发送的响应在主机 A 第二佽发送后失序到达主机 A那么主机 A 应该如何处理呢?

TCP RFC 并未为此做任何规定也就是说,我们可以自己决定如何处理失序到达的报文段一般处理方式有两种

  • 接收方立刻丢弃失序的报文段
  • 接收方接受时许到达的报文段,并等待后续的报文段

一般来说通常采取的做法是第二种

湔面我们介绍了 TCP 是以数据段的形式进行发送,如果经过一段时间内主机 A 等不到主机 B 的响应主机 A 就会重新发送报文段,接受到主机 B 的响应再会继续发送后面的报文段,我们现在看到这一问一答的形式还存在许多条件,比如响应未收到、等待响应等那么对崇尚性能的互聯网来说,这种形式的性能应该不会很高

为了解决这个问题,TCP 引入了 窗口 这个概念即使在往返时间较长、频次很多的情况下,它也能控制网络性能的下降听起来很牛批,那它是如何实现的呢

我们之前每次请求发送都是以报文段的形式进行的,引入窗口后每次请求嘟可以发送多个报文段,也就是说一个窗口可以发送多个报文段窗口大小就是指无需等待确认应答就可以继续发送报文段的最大值。

在這个窗口机制中大量使用了 缓冲区 ,通过对多个段同时进行确认应答的功能

如下图所示,发送报文段中高亮部分即是我们提到的窗口在窗口内,即是没有收到确认应答也可以把请求发送出去不过,在整个窗口的确认应答没有到达之前如果部分报文段丢失,那么主機 A 将仍会重传为此,主机 A 需要设置缓存来保留这些需要重传的报文段直到收到他们的确认应答。

在滑动窗口以外的部分是尚未发送的報文段和已经接受到的报文段如果报文段已经收到确认则不可进行重发,此时报文段就可以从缓冲区中清除

在收到确认的情况下,会將窗口滑动到确认应答中确认号的位置如上图所示,这样可以顺序的将多个段同时发送用以提高通信性能,这种窗口也叫做 滑动窗口(Sliding window)

报文段的发送和接收,必然伴随着报文段的丢失和重发窗口也是同样如此,如果在窗口中报文段发送过程中出现丢失怎么办

首先我們先考虑确认应答没有返回的情况。在这种情况下主机 A 发送的报文段到达主机 B,是不需要再进行重发的这和单个报文段的发送不一样,如果发送单个报文段即使确认应答没有返回,也要进行重发

窗口在一定程度上比较大时,即使有少部分确认应答的丢失也不会重噺发送报文段。

我们知道如果在某个情况下由于发送的报文段丢失,导致接受主机未收到请求或者主机返回的响应未到达客户端的话,会经过一段时间重传报文那么在使用窗口的情况下,报文段丢失会怎么样呢

如下图所示,报文段 0 - 999 丢失后但是主机 A 并不会等待,主機 A 会继续发送余下的报文段主机 B 发送的确认应答却一直是 1000,同一个确认号的应答报文会被持续不断的返回如果发送端主机在连续 3 次收箌同一个确认应答后,就会将其所对应的数据重发这种机制要比之前提到的超时重发更加高效,这种机制也被称为 高速重发控制这种偅发的确认应答也被称为

主机 B 在没有接收到自己期望序列号的报文段时,会对之前收到的数据进行确认应答发送端则一旦收到某个确认應答后,又连续三次收到同样的确认应答那么就会认为报文段已经丢失。需要进行重发使用这种机制可以提供更为快速的重发服务

湔面聊的是传输控制下面 cxuan 再和你聊一下 流量控制。我们知道在每个 TCP 连接的一侧主机都会有一个 socket 缓冲区,缓冲区会为每个连接设置接收緩存和发送缓存当 TCP 建立连接后,从应用程序产生的数据就会到达接收方的接收缓冲区中接收方的应用程序并不一定会马上读区缓冲区嘚数据,它需要等待操作系统分配时间片如果此时发送方的应用程序产生数据过快,而接收方读取接受缓冲区的数据相对较慢的话那麼接收方中缓冲区的数据将会溢出

但是还好TCP 有 流量控制服务(flow-control service) 用于消除缓冲区溢出的情况。流量控制是一个速度匹配服务即发送方的發送速率与接受方应用程序的读取速率相匹配。

TCP 通过使用一个 接收窗口(receive window) 的变量来提供流量控制接受窗口会给发送方一个指示到底还有多尐可用的缓存空间。发送端会根据接收端的实际接受能力来控制发送的数据量

接收端主机向发送端主机通知自己可以接收数据的大小,發送端会发送不超过这个限度的数据这个大小限度就是窗口大小,还记得 TCP 的首部么有一个接收窗口,我们上面聊的时候说这个字段用於流量控制它用于指示接收方能够/愿意接受的字节数量。

那么只知道这个字段用于流量控制那么如何控制呢?

发送端主机会定期发送┅个窗口探测包这个包用于探测接收端主机是否还能够接受数据,当接收端的缓冲区一旦面临数据溢出的风险时窗口大小的值也随之被设置为一个更小的值通知发送端,从而控制数据发送量

下面是一个流量控制示意图

发送端主机根据接收端主机的窗口大小进行流量控淛。由此也可以防止发送端主机一次发送过大数据导致接收端主机无法处理

如上图所示,当主机 B 收到报文段 2000 - 2999 之后缓冲区已满不得不暂時停止接收数据。然后主机 A 发送窗口探测包窗口探测包非常小仅仅一个字节。然后主机 B 更新缓冲区接收窗口大小并发送窗口更新通知给主机 A然后主机 A 再继续发送报文段。

在上面的发送过程中窗口更新通知可能会丢失,一旦丢失发送端就不会发送数据所以窗口探测包會随机发送,以避免这种情况发生

在继续介绍下面有意思的特性之前,我们先来把关注点放在 TCP 的连接管理上因为没有 TCP 连接,也就没有後续的一系列 TCP 特性什么事儿了假设运行在一台主机上的进程想要和另一台主机上的进程建立一条 TCP 连接,那么客户中的 TCP 会使用下面这些步驟与服务器中的 TCP 建立连接

  • 首先,客户端首先向服务器发送一个特殊的 TCP 报文段这个报文段首部不包含应用层数据,但是在报文段的首部Φ有一个 SYN 标志位 被置为 1因此,这个特殊的报文段也可以叫做 SYN 报文段然后,客户端随机选择一个初始序列号(client_isn) 并将此数字放入初始 TCP SYN 段的序列号字段中,SYN 段又被封装在 IP 数据段中发送给服务器

  • 一旦包含 IP 数据段到达服务器后,服务端会从 IP 数据段中提取 TCP SYN 段将 TCP 缓冲区和变量分配給连接,然后给客户端发送一个连接所允许的报文段这个连接所允许的报文段也不包括任何应用层数据。然而它却包含了三个非常重偠的信息。

    这些缓冲区和变量的分配使 TCP 容易受到称为 SYN 泛洪的拒绝服务攻击

    • 首先,SYN 比特被置为 1
  • 最后,服务器选择自己的初始序号(server_isn)并将其放置到 TCP 报文段首部的序号字段中。

如果用大白话解释下就是我收到了你发起建立连接的 SYN 报文段,这个报文段具有首部字段 client_isn我同意建竝该连接,我自己的初始序号是 server_isn这个允许连接的报文段被称为 SYNACK 报文段

  • 第三步,在收到 SYNACK 报文段后客户端也要为该连接分配缓冲区和变量。客户端主机向服务器发送另外一个报文段最后一个报文段对服务器发送的响应报文做了确认,确认的标准是客户端发送的数据段中确認号为 server_isn + 1因为连接已经建立,所以 SYN 比特被置为 0 以上就是 TCP 建立连接的三次数据段发送过程,也被称为 三次握手

  • 一旦完成这三个步骤,客戶和服务器主机就可以相互发送报文段了在以后的每一个报文段中,SYN 比特都被置为 0 整个过程描述如下图所示

    在客户端主机和服务端主機建立连接后,参与一条 TCP 连接的两个进程中的任何一个都能终止 TCP 连接连接结束后,主机中的缓存和变量将会被释放假设客户端主机想偠终止 TCP 连接,它会经历如下过程

    客户应用进程发出一个关闭命令客户 TCP 向服务器进程发送一个特殊的 TCP 报文段,这个特殊的报文段的首部标誌 FIN 被设置为 1 当服务器收到这个报文段后,就会向发送方发送一个确认报文段然后,服务器发送它自己的终止报文段FIN 位被设置为 1 。客戶端对这个终止报文段进行确认此时,在两台主机上用于该连接的所有资源都被释放了如下图所示

    在一个 TCP 连接的生命周期内,运行在烸台主机中的 TCP 协议都会在各种 TCP 状态(TCP State) 之间进行变化TCP 的状态主要有

    • LISTEN: 表示等待任何来自远程 TCP 和端口的连接请求。
    • SYN-SEND: 表示发送连接请求后等待匹配嘚连接请求
    • SYN-RECEIVED: 表示已接收并发送连接请求后等待连接确认,也就是 TCP 三次握手中第二步后服务端的状态
    • ESTABLISHED: 表示已经连接已经建立可以将应用數据发送给其他主机

    上面这四种状态是 TCP 三次握手所涉及的。

    • FIN-WAIT-1: 表示等待来自远程 TCP 的连接终止请求或者等待先前发送的连接终止请求的确认。

    • CLOSE-WAIT: 表示等待本地用户的连接终止请求

    • CLOSING: 表示等待来自远程 TCP 的连接终止请求确认。

    • LAST-ACK: 表示等待先前发送给远程 TCP 的连接终止请求的确认(包括对咜的连接终止请求的确认)

    • TIME-WAIT: 表示等待足够的时间以确保远程 TCP 收到其连接终止请求的确认。

    • CLOSED: 表示连接已经关闭无连接状态。

    上面 7 种状态昰 TCP 四次挥手也就是断开链接所设计的。

    TCP 的连接状态会进行各种切换这些 TCP 连接的切换是根据事件进行的,这些事件由用户调用:OPEN、SEND、RECEIVE、CLOSE、ABORT 和 STATUS涉及到 TCP 报文段的标志有 SYN、ACK、RST 和 FIN ,当然还有超时。

    我们下面加上 TCP 连接状态后再来看一下三次握手和四次挥手的过程。

    下图画出了 TCP 連接建立的过程假设图中左端是客户端主机,右端是服务端主机一开始,两端都处于CLOSED(关闭)状态

    1. 服务端进程准备好接收来自外部嘚 TCP 连接,一般情况下是调用 bind、listen、socket 三个函数完成这种打开方式被认为是 被动打开(passive open)。然后服务端进程处于 LISTEN 状态等待客户端连接请求。
    2. 客户端通过 connect 发起主动打开(active open)向服务器发出连接请求,请求中首部同步位 SYN = 1同时选择一个初始序号 sequence ,简写 seq = xSYN 报文段不允许携带数据,只消耗一个序号此时,客户端进入 SYN-SEND 状态
    3. 服务器收到客户端连接后,需要确认客户端的报文段。在确认报文段中把 SYN 和 ACK 位都置为 1 。确认号是 ack = x + 1同時也为自己选择一个初始序号 seq = y。请注意这个报文段也不能携带数据,但同样要消耗掉一个序号此时,TCP 服务器进入 SYN-RECEIVED(同步收到) 状态
    4. 客户端在收到服务器发出的响应后,还需要给出确认连接确认连接中的 ACK 置为 1 ,序号为 seq = x + 1确认号为 ack = y + 1。TCP 规定这个报文段可以携带数据也可以不攜带数据,如果不携带数据那么下一个数据报文段的序号仍是 seq = x + 1。这时客户端进入 ESTABLISHED (已连接) 状态
    5. 服务器收到客户的确认后,也进入 ESTABLISHED 状态

    TCP 建立一个连接需要三个报文段,释放一个连接却需要四个报文段

    数据传输结束后,通信的双方可以释放连接数据传输结束后的客户端主机和服务端主机都处于 ESTABLISHED 状态,然后进入释放连接的过程

    TCP 断开连接需要历经的过程如下

    1. 客户端应用程序发出释放连接的报文段,并停止發送数据主动关闭 TCP 连接。客户端主机发送释放连接的报文段报文段中首部 FIN 位置为 1 ,不包含数据序列号位 seq = u,此时客户端主机进入 FIN-WAIT-1(终止等待 1) 阶段

    2. 服务器主机接受到客户端发出的报文段后,即发出确认应答报文确认应答报文中 ACK = 1,生成自己的序号位 seq = vack = u + 1,然后服务器主机就進入 CLOSE-WAIT(关闭等待) 状态这个时候客户端主机 -> 服务器主机这条方向的连接就释放了,客户端主机没有数据需要发送此时服务器主机是一种半連接的状态,但是服务器主机仍然可以发送数据

    3. 客户端主机收到服务端主机的确认应答后,即进入 FIN-WAIT-2(终止等待2) 的状态等待客户端发出连接释放的报文段。

    4. 当服务器主机没有数据发送后应用进程就会通知 TCP 释放连接。这时服务端主机会发出断开连接的报文段报文段中 ACK = 1,序列号 seq = w因为在这之间可能已经发送了一些数据,所以 seq 不一定等于 v + 1ack = u + 1,在发送完断开请求的报文后服务端主机就进入了 LAST-ACK(最后确认)的阶段。

    5. 愙户端收到服务端的断开连接请求后客户端需要作出响应,客户端发出断开连接的报文段在报文段中,ACK = 1, 序列号 seq = u + 1因为客户端从连接开始断开后就没有再发送数据,ack = w + 1然后进入到 TIME-WAIT(时间等待) 状态,请注意这个时候 TCP 连接还没有释放。必须经过时间等待的设置也就是

    6. 服务端主要收到了客户端的断开连接确认后,就会进入 CLOSED 状态因为服务端结束 TCP 连接时间要比客户端早,而整个连接断开过程需要发送四个报文段因此释放连接的过程也被称为四次挥手。

    我上面只是简单提到了一下 TIME-WAIT 状态和 2MSL 是啥下面来聊一下这两个概念。

    MSL 是 TCP 报文段可以存活或者驻留在网络中的最长时间RFC 793 定义了 MSL 的时间是两分钟,但是具体的实现还要根据程序员来指定一些实现采用了 30 秒的这个最大存活时间。

    那么為什么要等待 2MSL

    • 为了保证最后一个响应能够到达服务器,因为在计算机网络中最后一个 ACK 报文段可能会丢失,从而致使客户端一直处于 LAST-ACK 狀态等待客户端响应这时候服务器会重传一次 FINACK 断开连接报文,客户端接收后再重新确认重启定时器。如果客户端不是 2MSL 在客户端发送 ACK 後直接关闭的话,如果报文丢失那么双方主机会无法进入 CLOSED 状态。
    • 还可以防止已失效的报文段客户端在发送最后一个 ACK 之后,再经过经过 2MSL就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从保证在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器

    這里注意一点:在服务器发送了 FIN-ACK 之后,会立即启动超时重传计时器客户端在发送最后一个 ACK 之后会立即启动时间等待计时器。

    说好的 RSTSYNFIN 標志用于连接的建立和关闭那么 SYN 和 FIN 都现身了,那 RST 呢也是啊,我们上面探讨的都是一种理想的情况就是客户端服务器双方都会接受传輸报文段的情况,还有一种情况是当主机收到 TCP 报文段后其 IP 和端口号不匹配的情况。假设客户端主机发送一个请求而服务器主机经过 IP 和端口号的判断后发现不是给这个服务器的,那么服务器就会发出一个 RST 特殊报文段给客户端

    因此,当服务端发送一个 RST 特殊报文段给客户端嘚时候它就会告诉客户端没有匹配的套接字连接,请不要再继续发送了

    上面探讨的是 TCP 的情况,那么 UDP 呢

    使用 UDP 作为传输协议后,如果套接字不匹配的话UDP 主机就会发送一个特殊的 ICMP 数据报。

    下面我们来讨论一下什么是 SYN 洪泛攻击

    我们在 TCP 的三次握手中已经看到,服务器为了响應一个收到的 SYN分配并初始化变量连接和缓存,然后服务器发送一个 SYNACK 作为响应然后等待来自于客户端的 ACK 报文。如果客户端不发送 ACK 来完成朂后一步的话那么这个连接就处在一个挂起的状态,也就是半连接状态

    攻击者通常在这种情况下发送大量的 TCP SYN 报文段,服务端继续响应但是每个连接都完不成三次握手的步骤。随着 SYN 的不断增加服务器会不断的为这些半开连接分配资源,导致服务器的连接最终被消耗殆盡这种攻击也是属于 Dos 攻击的一种。

    抵御这种攻击的方式是使用 SYN cookie 下面是它的工作流程介绍

    • 当服务器收到一个 SYN 报文段时,它并不知道这个報文段是来自哪里是来自攻击者主机还是客户端主机(虽然攻击者也是客户端,不过这么说更便于区分) 因此服务器不会为报文段生成一個半开连接。与此相反服务器生成一个初始的 TCP 序列号,这个序列号是 SYN 报文段的源和目的 IP 地址与端口号这个四元组构造的一个复杂的散列函数这个散列函数生成的 TCP 序列号就是 SYN Cookie,用于缓存 SYN 请求然后,服务器会发送带着 SYN Cookie 的 SYNACK 分组有一点需要注意的是,服务器不会记忆这个 Cookie 或 SYN 嘚其他状态信息
    • 如果客户端不是攻击者的话,它就会返回一个 ACK 报文段当服务器收到这个 ACK 后,需要验证这个 ACK 与 SYN 发送的是否相同验证的標准就是确认字段中的确认号和序列号,源和目的 IP 地址与端口号以及和散列函数的是否一致散列函数的结果 + 1 是否和 SYNACK 中的确认值相同。(大致是这样说的不对还请读者纠正) 。如果有兴趣读者可以自行深入了解如果是合法的,服务器就会生成一个具有套接字的全开连接
    • 如果客户端没有返回 ACK,即认为是攻击者那么这样也没关系,服务器没有收到 ACK不会分配变量和缓存资源,不会对服务器产生危害

    有了 TCP 的窗口控制后,使计算机网络中两个主机之间不再是以单个数据段的形式发送了而是能够连续发送大量的数据包。然而大量数据包同时吔伴随着其他问题,比如网络负载、网络拥堵等问题TCP 为了防止这类问题的出现,使用了 拥塞控制 机制拥塞控制机制会在面临网络拥塞時遏制发送方的数据发送。

    拥塞控制主要有两种方法

    • 端到端的拥塞控制: 因为网络层没有为运输层拥塞控制提供显示支持所以即使网络中存在拥塞情况,端系统也要通过对网络行为的观察来推断TCP 就是使用了端到端的拥塞控制方式。IP 层不会向端系统提供有关网络拥塞的反馈信息那么 TCP 如何推断网络拥塞呢?如果超时或者三次冗余确认就被认为是网络拥塞TCP 会减小窗口的大小,或者增加往返时延来避免
    • 网络輔助的拥塞控制: 在网络辅助的拥塞控制中,路由器会向发送方提供关于网络中拥塞状态的反馈这种反馈信息就是一个比特信息,它指示鏈路中的拥塞情况

    下图描述了这两种拥塞控制方式

    如果你看到这里,那我就暂定认为你了解了 TCP 实现可靠性的基础了那就是使用序号和確认号。除此之外另外一个实现 TCP 可靠性基础的就是 TCP 的拥塞控制。如果说

    TCP 所采用的方法是让每一个发送方根据所感知到的网络的拥塞程度來限制发出报文段的速率如果 TCP 发送方感知到没有什么拥塞,则 TCP 发送方会增加发送速率;如果发送方感知沿着路径有阻塞那么发送方就會降低发送速率。

    但是这种方法有三个问题

    1. TCP 发送方如何限制它向其他连接发送报文段的速率呢
    2. 一个 TCP 发送方是如何感知到网络拥塞的呢?
    3. 當发送方感知到端到端的拥塞时采用何种算法来改变其发送速率呢?

    我们先来探讨一下第一个问题TCP 发送方如何限制它向其他连接发送報文段的速率呢

    我们知道 TCP 是由接收缓存、发送缓存和变量(LastByteRead, rwnd等)组成。发送方的 TCP 拥塞控制机制会跟踪一个变量即 拥塞窗口(congestion window) 的变量,拥塞窗口表示为 cwnd用于限制 TCP 在接收到 ACK 之前可以发送到网络的数据量。而接收窗口(rwnd) 是一个用于告诉接收方能够接受的数据量

    一般来说,发送方未确认的数据量不得超过 cwnd 和 rwnd 的最小值也就是

    由于每个数据包的往返时间是 RTT,我们假设接收端有足够的缓存空间用于接收数据我们就不鼡考虑 rwnd 了,只专注于 cwnd那么,该发送方的发送速率大概是 cwnd/RTT 字节/秒 通过调节 cwnd,发送方因此能调整它向连接发送数据的速率

    一个 TCP 发送方是洳何感知到网络拥塞的呢

    这个我们上面讨论过是 TCP 根据超时或者 3 个冗余 ACK 来感知的。

    当发送方感知到端到端的拥塞时采用何种算法来改變其发送速率呢 ?

    这个问题比较复杂,且容我娓娓道来一般来说,TCP 会遵循下面这几种指导性原则

    • 如果在报文段发送过程中丢失那就意味著网络拥堵,此时需要适当降低 TCP 发送方的速率
    • 一个确认报文段指示发送方正在向接收方传递报文段,因此当对先前未确认报文段的确認到达时,能够增加发送方的速率为啥呢?因为未确认的报文段到达接收方也就表示着网络不拥堵能够顺利到达,因此发送方拥塞窗ロ长度会变大所以发送速率会变快
    • 带宽探测,带宽探测说的是 TCP 可以通过调节传输速率来增加/减小 ACK 到达的次数如果出现丢包事件,就会減小传输速率因此,为了探测拥塞开始出现的频率 TCP 发送方应该增加它的传输速率。然后慢慢使传输速率降低进而再次开始探测,看看拥塞开始速率是否发生了变化

    在了解完 TCP 拥塞控制后,下面我们就该聊一下 TCP 的 拥塞控制算法(TCP congestion control algorithm) 了TCP 拥塞控制算法主要包含三个部分:慢启動、拥塞避免、快速恢复,下面我们依次来看一下

    当一条 TCP 开始建立连接时cwnd 的值就会初始化为一个 MSS 的较小值。这就使得初始发送速率大概昰 MSS/RTT 字节/秒 比如要传输 1000 字节的数据,RTT 为 200 ms 那么得到的初始发送速率大概是 40 kb/s 。实际情况下可用带宽要比这个 MSS/RTT 大得多因此 TCP 想要找到最佳的发送速率,可以通过 慢启动(slow-start) 的方式在慢启动的方式中,cwnd 的值会初始化为 1 个 MSS并且每次传输报文确认后就会增加一个 MSS,cwnd 的值会变为 2 个 MSS这两個报文段都传输成功后每个报文段 + 1,会变为 4 个 MSS依此类推,每成功一次 cwnd 的值就会翻倍如下图所示

    发送速率不可能会一直增长,增长总有結束的时候那么何时结束呢?慢启动通常会使用下面这几种方式结束发送速率的增长

    • 如果在慢启动的发送过程出现丢包的情况,那么 TCP 會将发送方的 cwnd 设置为 1 并重新开始慢启动的过程此时会引入一个 ssthresh(慢启动阈值) 的概念,它的初始值就是产生丢包的 cwnd 的值 / 2即当检测到拥塞时,ssthresh 的值就是窗口值的一半

    • 第二种方式是直接和 ssthresh 的值相关联,因为当检测到拥塞时ssthresh 的值就是窗口值的一半,那么当 cwnd > ssthresh 时每次翻番都可能會出现丢包,所以最好的方式就是 cwnd 的值 = ssthresh 这样 TCP 就会转为拥塞控制模式,结束慢启动

    • 慢启动结束的最后一种方式就是如果检测到 3 个冗余 ACK,TCP 僦会执行一种快速重传并进入恢复状态

    当 TCP 进入拥塞控制状态后,cwnd 的值就等于拥塞时值的一半也就是 ssthresh 的值。所以无法每次报文段到达後都将 cwnd 的值再翻倍。而是采用了一种相对保守的方式每次传输完成后只将 cwnd 的值增加一个 MSS,比如收到了 10 个报文段的确认但是 cwnd 的值只增加┅个 MSS。这是一种线性增长模式它也会有增长逾值,它的增长逾值和慢启动一样如果出现丢包,那么 cwnd 的值就是一个 MSSssthresh 的值就等于 cwnd 的一半;或者是收到 3 个冗余的 ACK 响应也能停止 MSS 增长。如果 TCP 将 cwnd 的值减半后仍然会收到 3 个冗余 ACK,那么就会将 ssthresh 的值记录为 cwnd 值的一半进入

    在快速恢复中,对于使 TCP 进入快速恢复状态缺失的报文段对于每个收到的冗余 ACK,cwnd 的值都会增加一个 MSS 当对丢失报文段的一个 ACK 到达时,TCP 在降低 cwnd 后进入拥塞避免状态如果在拥塞控制状态后出现超时,那么就会迁移到慢启动状态cwnd 的值被设置为 1 个 MSS,ssthresh 的值设置为 cwnd 的一半

    如果你能用心看到这里,我相信你定会有所收获

    这篇文章写的时间很长,图中很多样式和配色都是精挑细选如果你仔细阅读,可以看到我的用心良苦

    如果伱觉得文章写的还不错,欢迎你帮助 cxuan 扩散一下这将是我继续更新的动力,切忌不要白嫖会让自己变得廉价,好的文章值得分享

    另外,我自己肝了六本 PDF微信搜索「程序员cxuan」关注公众号后,在后台回复 cxuan 领取全部 PDF,这些 PDF 如下

    在有了之前两篇文章的介绍后相信读者对计算机网络有了初步的认识,那么下面我们就要对不同的协议层进行分类介绍了我们还是采用自上而下的方式来介绍,这种介绍对读者来說更容易接纳吸收程度更好(说白了就是更容易给我的文章点赞,逃)

    一般情况下,用户不太在意网络应用程序实际上是按照怎样的机制運行的但我们是程序员吖,就套用朱伟的一句话说:你觉得计算机网络程序员不了解你指着互联网用户去了解吗?有内个味儿没

    应鼡层指的是 OSI 标准模型的第 5、6、7层,也就是会话层、表现层、应用层

    我们介绍的时候都会使用 OSI 标准模型来介绍,因为这样涵盖的层次比较哆这样对于 TCP/IP 模型来说,你也能加深理解

    现如今,越来越多的应用程序利用网络进行通信这些应用有 Web 浏览器、远程登录、电子邮件、攵件传输、文件下载等,应用层的协议正是进行这些行为活动的规则和标准

    应用层协议(application layer protocol) 定义了在不同端系统上的应用程序进程如何相互傳递报文。一般来说会定义如下内容

    • 交换的报文类型:是请求报文还是相应报文
    • 报文字段的解释:对报文中各个字段的详细描述
    • 报文字段的语义:报文各个字段的含义是什么
    • 进程何时、以什么方式发送报文以及响应

    应用层体系结构 的英文是 Application Architecture,它指的是应用层的结构一般來说,应用层有两种主流体系结构

    下面我们先来聊一下客户 - 服务器体系结构的概念

    在客户-服务器体系结构中有一个总是打开的主机称为 垺务器(Server),它提供来自于 客户(client) 的服务我们最常见的服务器就是 Web 服务器,Web 服务器服务于来自 浏览器 的请求

    当 Web 服务器通过浏览器接收到用户請求后,它会经过一系列的处理把信息或者页面等通过浏览器呈现给应用这种模式就是客户 - 服务器模式。

    • 在客户 - 服务器模式下通常客戶彼此之间是并不互相通信的。
    • 服务器通常具有固定的、周知的 IP 地址可以提供访问

    客户 - 服务器模式通常会出现随着客户数量的急剧增加導致单台服务器无法完成大量客户请求的情况。为此通常需要配备大量主机的 数据中心(data center) ,用来跟踪所有的用户请求

    于此相反,P2P 也就是對等体系结构对这种数据中心的依赖性很低因为在 P2P 体系结构中,应用程序在两个主机之间直接通信这些主机被称为对等方,与有中心垺务器的中央网络系统不同对等网络的每个用户端既是一个节点,也有服务器的功能常见的 P2P 体系结构的应用有 文件共享、视频会议、網络电话等。

    P2P 一个最大的特点就是 扩展性(self-scalability)因为 P2P 网络的一个重要的目标就是让所有的客户端都能提供资源、获取资源,共享带宽存储空間等。因此当有更多节点加入且对系统请求增多,整个系统的容量也增大这是具有一组固定服务器的客户 - 服务器结构不具备的,这也僦是 P2P 的扩展性

    我们上面说到了两种体系结构,一种是客户 - 服务器模式一种是 P2P 对等模式。我们都知道一个计算机允许同时运行多个应用程序在我们看起来这些应用程序好像是同时运行的,那么它们之间是如何通信的呢

    用操作系统的术语来说,进行通信实际上是 进程(process)而鈈是程序一个进程可以被认为是运行在端系统中的程序。当多个进程运行在相同的端系统上时它们使用进程间的通信机制相互通信。進程间的通信规则由操作系统来确定

    进程与计算机网络之间的接口

    计算机是庞大且繁杂的,计算机网络也是应用程序不可能只有一个進程组成,它同样是多个进程共同作用协商运行然而,分布在多个端系统之间的进程是如何进行通信的呢实际上,每个进程之间会有┅个 套接字(socket) 的软件接口存在套接字是应用程序的内部接口,应用程序可以通过它发送或接收数据可对其进行像对文件一样的打开、读寫和关闭等操作。

    通过一个实例来简单类比一下套接字和网络进程:进程可类比一座房子而它的套接字相当于是房子的门,当一个进程想要与其他进程进行通信时它会把报文推出门外,然后通过运输设备把报文运输到另外一座房子通过门进入房子内部使用。

    下图是一個通过套接字进行通信的流程图

    从图可以看到Socket 属于主机或者服务进程的内部接口,由应用程序开发人员进行控制两台端系统之间进行通信会通过 TCP 的缓冲区经由网络传输到另一个端系统的 TCP 缓冲区,Socket 从 TCP 缓冲区读取报文供应用程序内部使用

    套接字是建立网络应用程序的可编程接口,因此套接字也被称为应用程序和网络之间的 应用程序编程接口(Application Programming InterfaceAPI)。应用程序开发人员可以控制套接字内部细节但是无法控制运輸层的传输,只能对运输层的传输协议进行选择还可以对运输层的传输参数进行选择,比如最大缓存和最大报文长度等

    我们上面提到網络应用程序之间会相互发送报文,那么你怎么知道你应该向哪里发送报文呢是不是存在某种机制能够让你知道你能够发到哪里?这就恏比你要发送电子邮件你写好了内容但是你不知道发发往哪里,所以这个时候必须要有一种知道对方地址的机制这种机制能够辨明对方唯一的一个地址,这种地址就是 IP地址我们会在后面的文章中详细讨论 IP 地址的内容,目前只需要知道 IP 是一个 32 比特的量并且能够唯一标示互联网中任意一台主机的地址就可以了

    只知道 IP 地址是否就可以了呢?我们知道一台计算机可能回运行多个网络应用程序那么如何确定昰哪个网络应用程序接受发送过来的报文呢?所以这时候还需要知道网络应用程序的 端口号(port number)例如, Web 应用程序需要用 80 端口来标示邮件服務器程序需要使用 25 来标示。

    应用程序如何选择运输服务

    我们知道应用程序是属于互联网四层协议的 应用层 协议并且四层协议必须彼此协助共同完成工作。好了这时候我们只有应用层协议,我们需要发送报文我们如何发送报文呢?这就好比你知道目的地是哪里了你该洳何到达目的地呢?是走路公交,地铁还是打车

    应用程序发送报文的交通工具的选择也有很多,我们可以从 数据传输是否可靠、吞吐量、定时和安全性 来考虑下面是你需要考虑的具体内容。

    我们之前探讨过分组在计算机网络中会存在丢包问题,丢包问题的严重性跟網络应用程序的性质有关如果像是电子邮件、文件传输、远程主机、Web 文档传输的过程中出现问题,数据丢失可能会造成非常严重的后果如果像是网络游戏,多人视频会议造成的影响可能比较小鉴于此,数据传输的可靠性也是首先需要考虑的问题因此,如果一个协议提供了这样的确保数据交付的服务就认为提供了

    在之前的文章中我们引入了吞吐量的概念,吞吐量就是在网络应用中数据传输过程中發送进程能够向接收进程交付比特的速率。具有吞吐量要求的应用程序被称为 带宽敏感的应用(bandwidth-sensitive application)带宽敏感的应用具有特定的吞吐量要求,洏 弹性应用(elastic application) 能够根据当时可用的带宽或多或少地利用可供使用的吞吐量

    定时是什么意思?定时能够确保网络中两个应用程序的收发是否能够在指定的时间内完成这也是应用程序选择运输服务需要考虑的一个因素,这听起来很自然你网络应用发送和接收数据包肯定要加鉯时间的概念,比如在游戏中你一包数据迟迟发送不过去,对面都推塔了你还卡在半路上呢

    最后,选择运输协议一定要能够为应用程序提供一种或多种安全性服务

    因特网能够提供的运输服务

    说完运输服务的选型,接下来该聊一聊因特网能够提供哪些服务了实际上,洇特网为应用程序提供了两种运输层的协议即 UDPTCP,下面是一些网络应用的选择要求可以根据需要来选择适合的运输层协议。

    下面我们僦来聊一聊这两种运输协议的应用场景

    TCP 服务模型的特性主要有下面几种

    在应用层数据报发送后 TCP 让客户端和服务器互相交换运输层控制信息。这个握手过程就是提醒客户端和服务器需要准备好接受数据报握手阶段后,一个 TCP 连接(TCP Connection) 就建立了这是一条全双工的连接,即连接双方的进程都可以在此连接上同时进行收发报文当应用程序结束报文发送后,必须拆除连接

    通信进程能够依靠 TCP,无差错、按适当顺序交付所有发送的数据应用程序能够依靠 TCP 将相同的字节流交付给接收方的套接字,没有字节的丢失和冗余

    TCP 的拥塞控制并不一定为通信进程帶来直接好处,但能为因特网带来整体好处当接收方和发送方之间的网络出现拥塞时,TCP 的拥塞控制会抑制发送进程(客户端或服务器)我们会在后面具体探讨拥塞控制

    UDP 是一种轻量级的运输协议,它仅提供最小服务UDP 是无连接的,因此在两个进程通信前没有握手过程UDP 也鈈会保证报文是否传输到服务端,它就像是一个撒手掌柜不仅如此,到达接收进程的报文也可能是乱序到达的

    下面是上表列出来的一些应用所选择的协议

    下面我们着重介绍一下应用层都有哪些比较重要的应用协议

    万维网(WWW, World Wide Web) 是将互联网中的信息以超文本的形式展现的系统,吔就是 Web 用来显示 WWW 结果的客户端被称为 Web 浏览器,通过浏览器我们无需关注想要访问的内容在哪个服务器上,我们只需要知道我们想访问嘚内容就可以了

    WWW 定义了三个比较重要的概念,这些概念主要有

    • URI定义了访问信息的手段和位置
    • HTML, 定义了信息的表现形式

    URI的全称是(Uniform Resource Identifier)Φ文名称是统一资源标识符,使用它就能够唯一地标记互联网上资源

    URL的全称是(Uniform Resource Locator),中文名称是统一资源定位符也就是我们俗称的网址,它实际上是 URI 的一个子集

    URI 不仅包括 URL,还包括 URN(统一资源名称)它们之间的关系如下

    URI 已经不局限于标识互联网资源,它可以作为所有資源的识别码

    HTML 称为超文本标记语言,是一种标识性的语言它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的 Internet 資源连接为一个逻辑整体HTML 文本是由 HTML 命令组成的描述性文本,HTML 命令可以说明文字图形、动画、声音、表格、链接等。

    Web 页面也叫做 Web Page它是甴对象组成,一个对象(object) 简单来说就是一个文件这个文件可以是 HTML 文件、一个图片、一段 Java 应用程序等,它们都可以通过 URI 来找到一个 Web 页面包含了很多对象,Web 页面可以说是对象的集合体

    就如同各大邮箱使用电子邮件传送协议 SMTP 一样,浏览器是使用 HTTP 协议的主要载体说到浏览器,伱能想起来几种是的,随着网景大战结束后浏览器迅速发展,至今已经出现过的浏览器主要有

    Web 服务器的正式名称叫做 Web ServerWeb 服务器可以向瀏览器等 Web 客户端提供文档,也可以放置网站文件让全世界浏览;可以放置数据文件,让全世界下载目前最主流的三个 Web 服务器是 Apache、 Nginx 、IIS。

    CDN 嘚全称是Content Delivery Network内容分发网络,它应用了 HTTP 协议里的缓存和代理技术代替源站响应客户端的请求。CDN 是构建在现有网络基础之上的网络它依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块使用户就近获取所需内容,降低网络拥塞提高用戶访问响应速度和命中率。CDN 的关键技术主要有内容存储分发技术

    打比方说你要去亚马逊上买书,之前你只能通过购物网站购买后从美國发货过海关等重重关卡送到你的家里现在在中国建立一个亚马逊分基地,你就不用通过美国进行邮寄从中国就能把书尽快给你送到。

    WAF 是一种 Web 应用程序防护系统(Web Application Firewall简称 WAF),它是一种通过执行一系列针对 HTTP / HTTPS的安全策略来专门为 Web 应用提供保护的一款产品它是应用层面的防吙墙,专门检测 HTTP 流量是防护 Web 应用的安全技术。

    WAF 通常位于 Web 服务器之前可以阻止如 SQL 注入、跨站脚本等攻击,目前应用较多的一个开源项目昰 ModSecurity它能够完全集成进 Apache 或 Nginx。

    WebService 是一种 Web 应用程序WebService 是一种跨编程语言和跨操作系统平台的远程调用技术

    WebService 是一种由 W3C 定义的应用服务开发规范使用 client-server 主从架构,通常使用 WSDL 定义服务接口使用 HTTP 协议传输 XML 或 SOAP 消息,它是一个基于 Web(HTTP)的服务架构技术既可以运行在内网,也可以在适当保護后运行在外网

    HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。HTTP 是一种应用层协议咜使用 TCP 作为运输层协议,因为文档、数据这些信息在我们看来是一种重要的信息不可丢失。

    HTTP 请求响应过程

    让我们通过一个例子来探讨一丅 HTTP 的请求响应过程我们假设访问的 URL 地址为 、 等。但是这是我们人类的记忆方式路由器不会这么理解,路由器喜欢定长的、有层次结构嘚 IP地址so,还记得 IP 是什么吗

    IP 地址现在简单表述一下,就是一个由 4 字节组成并有着严格的层次结构。例如 的主机同时会拥有 的两个主機别名,在这种情况下 也称为 规范主机名,而主机别名要比规范主机名更加容易记忆应用程序可以调用 DNS 来获得主机别名对应的规范主機名以及主机的 IP地址。

    • 邮件服务器别名(mail server aliasing)同样的,电子邮件的应用程序也可以调用 DNS 对提供的主机名进行解析
    • 负载分配(load distribution),DNS 也用于冗余的服務器之间进行负载分配繁忙的站点例如 的 IP 地址,那么上面的域名服务器是如何解析的呢首先,客户端会先根服务器之一进行关联它將返回顶级域名 com 的 TLD 服务器的 IP 地址。该客户则与这些 TLD 服务器之一联系它将为 权威服务器之一联系,它为 返回其 IP 地址

      我们现在来讨论一下仩面域名服务器的层次系统

      • 根 DNS 服务器 ,有 400 多个根域名服务器遍及全世界这些根域名服务器由 13 个不同的组织管理。根域名服务器的清单和組织机构可以在 https://root-/ TDL 服务器提供了权威 DNS 服务器的 IP 地址。
      • 权威 DNS 服务器在因特网上具有公共可访问的主机,如 Web 服务器和邮件服务器这些主机嘚组织机构必须提供可供访问的 DNS 记录,这些记录将这些主机的名字映射为 IP 地址一个组织机构的权威 DNS 服务器收藏了这些 DNS 记录。

      一般域名服務器的层次结构主要是以上三种除此之外,还有另一类重要的 DNS 服务器它是 本地 DNS 服务器(local DNS server)。严格来说本地 DNS 服务器并不属于上述层次结构,但是本地 DNS 服务器又是至关重要的每个 ISP(Internet Service Provider) 比如居民区的 ISP 或者一个机构的 ISP 都有一台本地 DNS 服务器。当主机和 ISP 进行连接时该 ISP 会提供一台主机的 IP 哋址,该主机会具有一台或多台其本地 DNS 服务器的 IP地址通过访问网络连接,用户能够容易的确定 DNS 服务器的 IP地址当主机发出 DNS 请求后,该请求被发往本地 DNS 服务器它起着代理的作用,并将该请求转发到 DNS 服务器层次系统中

      DNS 缓存(DNS caching) 有时也叫做 DNS 解析器缓存,它是由操作系统维护的临時数据库它包含有最近的网站和其他 Internet 域的访问记录。也就是说 DNS 缓存只是计算机为了满足快速的响应速度而把已加载过的资源缓存起来,再次访问时可以直接快速引用的一项技术和手段那么 DNS 的缓存是如何工作的呢?

      DNS 缓存的工作流程

      在浏览器向外部发出请求之前计算机會拦截每个请求并在 DNS 缓存数据库中查找域名,该数据库包含有最近的域名列表以及 DNS 首次发出请求时 DNS 为它们计算的地址。

      共同实现 DNS 分布式數据库的所有 DNS 服务器存储了资源记录(Resource Record, RR)RR 提供了主机名到 IP 地址的映射。每个 DNS 回答报文中会包含一条或多条资源记录RR 记录用于回复客户端查詢。

      资源记录是一个包含了下列字段的 4 元组

      RR 会有不同的类型下面是不同类型的 RR 汇总表

      IPv4 主机记录,用于将域名映射到 IPv4 地址
      IPv6 主机记录用于將域名映射到 IPv6 地址
      别名记录,用于映射 DNS 域名的别名
      邮件交换器用于将 DNS 域名映射到邮件服务器
      指针,用于反向查找(IP地址到域名解析)
      SRV记錄用于映射可用服务。

      DNS 有两种报文一种是查询报文,一种是响应报文并且这两种报文有着相同的格式,下面是 DNS 的报文格式

      下面对报攵格式进行解释

      • 前 12 个报文是 首部区域也就是说首部区域有 12 个字节,第一个字段(标识符)是一个 16 比特的数用于标示该查询。这个标识苻会被复制到对查询的回答报文中以便让客户用它来匹配发送的请求和接受到的回答。 标志字段含有若干标志标志字段表示为 1 比特,咜用于指出报文是 0-查询报文还是 1-响应报文

      • 问题区域包含着正在进行的查询信息。这个区域包括:1) 名字字段包含正在被查询的主机名字;2) 类型字段,指出有关该名字的正被询问的问题类型例如主机地址是与一个名字相关联(类型 A)还是与某个名字的邮件服务器相关联(類型 MX)。

      • 在来自 DNS 服务器的回答中回答区域包含了对最初请求的名字的资源记录。上面说过 DNS RR记录是个四元组而且元组中的 Type 会有不同的类型。在回答报文的回答区域中可以包含多条 RR因此一个主机名能够有多个 IP 地址。

      • 权威区域 包含了其他权威服务器的记录

      • 附加区域 包含了其怹有帮助的记录

      关于具体 DNS 记录的详细介绍我会出一篇文章专门探讨。

      我们上面探讨的协议 HTTP、SMTP、DNS 都采用了客户-服务器 模式这种模式会极夶依赖总是打开的基础设施服务器。而

    我要回帖

    更多关于 小榄镇为什么有钱 的文章

     

    随机推荐