
我们自己写的应用程序就是在应用层
虽然应用层里面有一些现成的协议,但是在实际工作中也会存在 自定义应用层协议(发明协议?协议就是约定,约定好客户端和服务器按照啥样的格式来传输数据)
那么应用层协议如何约定呢?
例如前面我们写的回显服务器实现中,隐含了应用层协议的约定。约定了:每个请求,都是以 /n 结尾;每个响应,都是以 /n 结尾 。(scanner.next();)
自定义应用层协议,需要从两个角度入手:
如我们点外卖:
交互中涉及到哪些信息的传递,和需求又是密切相关
点击某个商家,涉及到网络交互
方式一:一种典型的约定方式,直接使用简单分隔符来对不同部分的信息做区分,考虑获取商家列表,约定的数据组织格式
使用;以及 /n 都是可以替换成其他符号的
方式二:一种典型的数据约定格式,使用固定长度,来区分从哪里到哪里是一个信息
请求:(一个请求固定 12 个字节)

响应:

方式三:方式一和方式二混合搭配,有些字段使用固定长度,有些字段使用分隔符。
方式四:通过 XML 的格式来约定数据
请求:

响应:

XML 格式和 HTML 格式非常像,都是通过标签这样的结构来组织数据的。标签一般是成对出现的,表达了 “树形结构”(多级嵌套)。
方式五:json 相比于 xml 更常用的数据组织形式
请求:

响应:

使用 { } 来包含一些 “键值对”。键值对之间,使用逗号分割,每个键值对的键和值之间使用冒号分割
json 要求键的部分必须是字符串,而值的部分,可以是数字,可以是字符串,还可以是数组(使用 [ ] ),还可以是另外一个 json。
json 是当下用来自定义协议的时候,非常常用的格式!也有很多相关的第三方库,可以用来操作 json 数据。
方式六:还有一些其他的 “二进制” 组织格式,protobuffer,thift 等
- 像 xml 和 json 都是属于文本格式(优势是可读性高,劣势是效率低,占用的带宽更多)
- protobuffer,thift 都是二进制格式,格式上就要更加的复杂(优势是效率高,占用带宽低,劣势是可读性差)
应用层协议数据格式有很多种,在实际开发中要根据实际的情况来决定使用哪种更合适
拓展带宽的相关知识:
在国内,带宽是最贵的硬件成本,和 CPU ,内存,硬盘相比。升级服务器的带宽花的钱是比 CPU ,内存啥的升级要贵很多。
应用层协议不仅仅是可以自己写代码自定义协议,也有一些现成的协议,可以直接使用的,最著名的协议就是 HTTP 协议(后面的文章会更新介绍)
传输层协议是操作系统内核中已经包含好的
其中包含了
认识协议的细节,往往要认识协议的报文格式

使用 IP 地址,来区分当前是哪个主机,一个主机上可能有多个应用程序,使用端口号来区分应用程序。
UDP 长度:表示了 UDP 数据报有多长。(注意:这里此处有个重大缺陷,此处的长度,单位是字节,2个字节,能表示的最大长度是 65535 => 64KB => 一个 UDP 数据报最长就是 64KB,由于当时创建的时候,64KB 算大的,但是目前而言,如果代码中使用 UDP ,需要保证一个数据报(一个 DatagramPacket)最大不能超过 64KB)
举例搜狗搜索,搜索的结果有广告和非广告两部分
在入口服务器和广告服务器之间本来是使用 UDP 进行交互,在业务发展的过程中,一次次传输的数据越来越接近 64KB 了,为了解决这个问题,提出了两种方案。
- 在应用层把广告数据拆分成多个部分,使用多个 UDP 数据报来传输。接收这一段,把拆成的多个包,进行组合。(方案可行,但是代码会很复杂,网络通信有个特点,后发先至)
如我们的客户端按顺序发送 1 2 3 ,通常情况下,收到的顺序和发送的顺序是一致的,但是网络出现一些抖动,很容易让接收顺序和发送顺序不一致,也有办法解决这个问题,但是要花费很多的代价 ,为了控制顺序,就得整队,整队就有额外的开销,就得消耗时间。
- 实际使用的方案,直接使用 TCP 替代 UDP,TCP 没有长度限制
会有人问为什么不把 UDP 协议升级更新一下,改为 4 个字节或者 8 个字节呢?
UDP 已经内置到各个操作系统内核中了,发布到全世界无数个主机中了,想要进行升级,就得要求全世界的主机的操作系统都统一升级到这个版本的 UDP 才行,万一有部分没升级,UDP 就无法工作了。(务必要考虑到升级带来的影响,很多的升级操作,都要考虑到 “兼容性”)
网络传输中,传输的数据,不一定是准确无误的!
本质上是光信号 / 电信号,使用不同频率的光信号,表示 1 - 0,使用不同电频的电信号,表示 1 - 0,传输过程中,信号是可能受到干扰的!(尤其是无线,更容易受到干扰),干扰就可能造成 “比特反转” ,接收方,收到了数据之后,就得验证下,看看当前的数据是否是正确的!(验货)
例如买瓷砖,我们会验证瓷砖数量,款式,破损情况。
校验和可以认为是针对数据特征进行的 “摘要”(相当于瓷砖数量和款式),接收方就可以根据校验和来进行检查了。
UDP 传输数据,网络上的数据是可能受到干扰
发送的时候,针对要传输的数据,计算一个 “校验和” (相当于配置单)
发送的时候,把数据和校验和一起发送过去
接收的时候,针对收到的数据重新计算校验和,对比一下自己计算的校验和和发来的校验和是否是一样的,如果是一样的,就说明数据没啥问题,不一样就有问题。
UDP 使用的校验和算法,是一种非常简单的 CRC 算法(循环冗余校验和)
把数据的每个字节,都往上加,如果超出了范围(2 字节),溢出的部分就不要了,所有的字节都累加完了,得到的结果就是校验和了
如果检验和相同,输入的字节一定完全相同吗?好像也不一定
10 = 9 + 1;10 = 8 + 2; 10 = 7 +3;…
确实可能存在这种情况,但是这是一种非常小的概率事件,如果校验和不同,可以认为数据一定是传输过程中错了,但是校验和不同,不能认为 100% 的确认数据就一定没错(有可能正好两个地方错一块去了,导致校验和没变),但是因为数据发生传输错误的概率不大,能够错到一块,并且校验和没发生改变,这种概率更是少之又少。(工程上就忽略不计)
校验和,不仅仅是在 UDP 这里,很多的别的地方也会涉及到,只要是数据传输可能出现问题,都可以使用校验和的思想。
注意:哪些应用层协议基于 UDP 只能靠硬背
基于UDP的应用层协议:
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
当然,也包括你自己写UDP程序时自定义的应用层协议
扩展问题
经典面试题:
以上两个问题答案类似,都可以参考TCP的可靠性机制在应用层实现类似的逻辑:(后文详解TCP)
例如:
- 引入序列号,保证数据顺序;
- 引入确认应答,确保对端收到了数据;
- 引入超时重传,如果隔一段时间没有应答,就重发数据;
……
由于 TCP 协议很重要切内容比较复杂过多,请看下篇文章详解 TCP 协议
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt