草庐IT

HTTP、WebSocket、MQTT、TCP的区别和联系

王同学LM 2024-03-26 原文

3个应用层协议

HTTP、WebSocket、MQTT都是应用层协议。

  • HTTP(HyperText Transfer Protocol)主要用于在Web浏览器和Web服务器之间传输数据,例如显示Web页面、文件下载、上传等操作,属于请求-响应协议。
  • WebSocket也是应用于浏览器和Web服务器之间进行双向通信,提供了实时交互的能力。
  • MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布-订阅模式的消息传输协议。MQTT协议主要用于物联网设备之间的通信,具有低带宽、低能耗、可靠性高、支持异步通信等特点。

我们使用HTTP和WebSocket协议在Web应用程序中进行数据交互,使用MQTT在物联网设备之间进行数据传输。

1个传输层协议

TCP(Transmission Control Protocol)是一种传输层协议,提供可靠的、面向连接的数据传输服务。TCP协议主要用于保证数据的可靠传输,采用三次握手协议建立连接,通过确认和重传机制保证数据的可靠性。 

WebSocket和HTTP协议的关系

WebSocket协议在HTTP协议之上建立,通过HTTP的Upgrade头部将HTTP协议升级为WebSocket协议。在建立WebSocket连接之前,客户端和服务器之间必须先建立HTTP连接。因此,WebSocket可以看作是一种在HTTP连接之上的新协议,它在原有的HTTP基础上增加了双向实时通信的功能,不需要每次请求都建立连接,可以保持持久连接。

HTTP协议本身是一种请求-响应协议,客户端通过发送请求,服务器接收请求并返回响应。在这个过程中,服务器不能主动向客户端发送消息,只有在接收到客户端请求后才能返回响应。这种单向通信的限制使得HTTP协议不能实现实时双向通信的功能,对于需要实时交互的应用来说,HTTP协议的性能和效率都比较低。

WebSocket协议的出现解决了这个问题。WebSocket协议建立一个持久性的TCP连接,使得客户端和服务器之间可以实时双向通信。当客户端和服务器之间建立了WebSocket连接后,客户端可以随时向服务器发送消息,服务器也可以主动向客户端发送消息,而不必等待客户端的请求。

因此,WebSocket和HTTP协议有着紧密的关系,WebSocket协议建立在HTTP协议之上,并且在使用WebSocket协议之前,需要先建立HTTP连接。这时,HTTP协议起到了类似TCP中握手的作用

  1. 客户端向服务器发送HTTP请求,请求头部包含Upgrade和Connection字段,表示客户端请求升级到WebSocket协议。
  2. 服务器收到请求后,根据请求头部中的Upgrade字段,判断是否支持升级到WebSocket协议。
  3. 如果服务器支持升级到WebSocket协议,则返回HTTP响应,响应头部包含Upgrade和Connection字段,表示服务器同意升级到WebSocket协议。
  4. 客户端收到服务器的响应后,根据响应头部中的Upgrade和Connection字段,确认服务器同意升级到WebSocket协议,并开始使用WebSocket协议进行通信。

由于WebSocket协议建立在HTTP协议之上,因此WebSocket协议也继承了HTTP协议的一些特性,例如可以使用HTTP的身份认证和安全机制等。

有关HTTP、WebSocket、MQTT、TCP的区别和联系的更多相关文章

  1. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  2. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  3. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  4. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  5. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  7. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  8. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  9. ruby - 这两段代码有什么区别? - 2

    打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性

  10. ruby - Ruby 中 .next 和 .succ 的区别 - 2

    Ruby中的Fixnum方法.next和.succ有什么区别?看起来它的工作原理是一样的:1.next=>21.succ=>2如果有什么不同,为什么有两种方法做同样的事情? 最佳答案 它们是等价的。Fixnum#succ只是Fixnum#next的同义词。他们甚至在thereferencemanual中共享同一block. 关于ruby-Ruby中.next和.succ的区别,我们在StackOverflow上找到一个类似的问题: https://stacko

随机推荐