精华内容
下载资源
问答
  • 主要介绍了vue发送websocket请求和http post请求的方法,本文通过实例代码给大家介绍非常详细,具有一定参考借鉴价值 ,需要朋友可以参考下
  • <p>The vue.js app connects perfectly fine to the websocket and works. However, the GET requests to <code>192.168.99.100:8080/meows</code> and other endpoints all hit the <code>nginx 502 bad gateway...
  • 让我们先简单回顾一下之前谈到内容,AJAX是一种无页面刷新获取服务器资源混合技术。...现在,我们将要简要了解“跨域共享资源”另外两种方式:WebSocketpostMessage。让我们先大概看看他们是什么,以...

    让我们先简单回顾一下之前谈到的内容,AJAX是一种无页面刷新的获取服务器资源的混合技术。而基于浏览器的“同源策略”,不同“域”之间不可以发送AJAX请求。但是在某些情境下,我们需要“跨域获取资源”,为了满足这一需求,我们可以使用“JSONP”与“CORS”两种技术。

    现在,我们将要简要了解“跨域共享资源”的另外两种方式:WebSocket 和 postMessage。让我们先大概看看他们是什么,以及究竟是基于怎样的原理,满足了我们的需求 - “跨域获取资源”。

    一、WebSocket

    基于维基百科的定义,WebSocket是一种在单个TCP连接上进行全双工通讯的协议。在这里我并不打算解释“TCP连接”和“全双工通讯”这两个专业术语(这样做会让这篇文章变得很长,而且也偏离了我们的主题),让我们聚焦这段定义的最后两个字协议

    说到协议,你是否联想到“HTTP协议”?没错,HTML5标准之所以提出了一种新的互联网通信协议 - WebSocket,就是为了弥补在某些情景下使用HTTP协议通信的一些不足。但是注意,这并不意味WebSocket协议就可以完全取代HTTP协议了,其实两者的关系更像是两兄弟,各自有着各自擅长的领域,而且时不时还一同协作解决难题。

    那么上面提到的某些情景具体是指什么呢?答案是“服务端与客户端的双向通信”。我们知道,当我们使用HTTP协议时,客户端与服务端的通信模式始终是由客户端向服务端发送请求,服务端只负责验证请求并返回响应。

    我们可以这样想象,在HTTP协议下,服务端扮演着“守门人”的角色,而客户端则是一个邮局,它每发送一个请求就像是委托一个信使携带一封信(信里注明自己的身份和需要获取资源的名称)到服务端,当信使到达时,“守门人”会拆开信封,检查里面的身份信息,如果身份合法则打开资源宝库的大门,将相应的资源交给信使,令其返回给客户端。

    在这个故事里,服务端的角色有些枯燥呆板对吧?不仅如此,故事中服务端扮演的“守门人”角色还患有严重的脸盲症,在工作中他只“认信不认人”,也就是说客户端发送的每一个请求,对于服务而言都是全新的,守门人不会因为信使上次来过,或是收到两次相同的信而觉得眼熟,对信使有额外的寒暄。这也就是为什么我们说HTTP协议是“无状态的”。乍看起来,这似乎有些不合理,但是这种设计却使服务器的工作变得简单可控,提升了服务器的工作效率。

    但是这样的设计仍然存在两个问题:

    1. 每一个请求都需要身份验证,这对于用户而言意味着需要在每一次发送请求时输入身份信息;
    2. 当客户端所请求的资源是动态生成的时,客户端无法在资源生成时得到通知(还记得吧,服务器只是一个原地不动的“守门人”);

    如何解决这两个问题呢?对于前者,答案是使用“Cookie”,而对于后者,则轮到我们今天的主角“WebSocket”大显身手。

    在讨论WebSocket之前,让我们先稍微绕点路,谈谈“Cookie”是如何解决“每一个请求都需要身份验证”的问题的。

    (一)为HTTP协议添加状态 - Cookie

    我们之前提到,HTTP协议下,客户端与服务端的通信是“无状态”的,也就是说,如果服务器中的某部分资源是由某个客户专属的,那么每当这个客户想要获取资源时,都需要首先在浏览器中输入账号密码,然后再发送请求,并在被服务器识别身份信息成功后获取请求的资源。我们当然不想每次发送一个请求都要输入一遍账号密码,因此我们需要Cookie,这个既可以存储在浏览器,又会被浏览器发送HTTP请求时默认发送至服务端,并且还受浏览器“同源策略”保护的东西帮助我们提高发起一次请求的效率。

    在有了Cookie之后,我们可以在一次会话中(从用户登录到浏览器关闭)只输入一次账号密码,然后将其保存在Cookie中,在整个会话期间,Cookie都会伴随着HTTP请求的发送被服务器识别,从而避免了我们重复的输入身份信息。

    不仅如此,基于Cookie的特性:可以保存在浏览器内,还会在浏览器发送HTTP请求时默认携带,服务端也可以操作Cookie。Cookie还可以帮助我们节省网络请求的发起数量。例如,当我们在制作一个购物网站时,我们当然不希望用户在每添加一个商品到购物车就向服务器发送一个请求(请求数量越少,服务器压力就越小),此时,我们就可以将添加商品所导致的数据变动存储在Cookie内,然后等待下次发送请求时,一并发送给服务器处理。

    现在我们可以说,Cookie的出现,为无状态的HTTP协议通信添加了状态。

    最后需要注意,Cookie大多数情况下,都保存着用户的身份信息,因此各种恶意攻击者对于Cookie的攻击便花样百出,层出不穷。其本质上就是想要获得用户的Cookie,再利用其中的身份信息伪装成用户获取相应资源,而浏览器的“同源策略”本质上就是保护用户的Cookie信息不会泄露。

    (二)让服务器也动起来 - WebSocket

    绕了一个小弯,现在可以回过头来继续谈谈我们的主角WebSocket了。再让我们回忆一下WebSocket要解决的问题:

    客户端无法获知请求的动态资源何时到位“,让我们描述的更详细一点,有时候客户端想要请求的资源,服务器需要一定时间后才能返回(比如该资源依赖于其他服务器的计算返回结果),由于在HTTP协议下,网络通信是单向的,因此服务器并不具备当资源准备就绪时,通知浏览器的功能(因为我们要保障服务器的工作效率)。因此,基于HTTP协议通常的做法是,设置一个定时器,每隔一定时间由浏览器向服务器发送一次请求以探测资源是否到位。

    这种做法显然浪费了很多请求,换句话说,浪费了很多带宽(我们每个请求都要携带Cookie和报头,这些都会占用带宽传输),不仅低效率,而且也不够优雅。

    理所当然的,在这种情况下,我们希望当服务器资源到位时,能够主动通知浏览器并返回相应资源。而为了实现这一点,HTML5标准推出了WebSocket协议,使浏览器和服务器实现了双向通信,更妙的是,除了IE9及以下的IE浏览器,所有的浏览器都支持WebSocket协议。

    让我们也同样构建一个基于WebSocket协议的心智模型,在这个心智模型中,服务端扮演的角色发生了一些改变,服务端不再只是一个“守门人”,同时它也运营着一个和客户端一样的“邮局”,也就是说,他也拥有了可以向客户端发送数据的能力。至此一个完整的基于WebSocket协议的通信流程为:

    客户端派发一个信使向服务器送信,服务器扮演的“守门人”检查信件,发现信件中写到“让我们用更加潮流的WebSocket方式交流吧”,服务器在在信件末尾添加上一句“没问题,浏览器伙计”,让信使原路返回告知浏览器。当浏览器再次向服务器告知收到消息时(第三次握手),服务器就开始运转“邮局”,向客户端派发信使与浏览器互发信息,转发资源。

    让我们看看这个模型的具体实现:

    下面是客户端告知服务端要升级为WebSocket协议的报头:

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
    复制代码

    下面是服务端向客户端返回的响应报头:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    Sec-WebSocket-Protocol: chat
    复制代码

    想知道这些报头中的字段中代表什么?可以参考维基百科下的说明。

    (三)客户端发起WebSocket请求

    既然我们已经为了解释“什么是WebSocket”,“WebSocket的意义”花了那么多篇幅,那么不妨添加上最后一个环节,让这个主题变得更加完整,接下来我们将要简单讲解一下客户端如何发起一个WebSocket请求。

    像发起AJAX请求一样,发起WebSocket请求需要借助浏览器提供的WebSocket对象,该对象提供了用于创建和管理WebSocket连接,以及通过该连接收发数据的API。所有的浏览器都默认提供了WebSocket对象。让我们看看该对象的用法:

    和使用XHRHttpRequest对象一样,我们首先要实例化一个WebSocket对象:

    var ws = new WebSocket("wss://echo.websocket.org")
    复制代码

    传入的参数为响应WebSocket请求的地址。

    同样类似AJAX的是,WebSocket对象也有一个readyState属性,用来表示对象实例当前所处的链接状态,有四个值:

    • 0:表示正在连接中(CONNECTING);
    • 1:表示连接成功,可以通信(OPEN);
    • 2:表示连接正在关闭(CLOSING);
    • 3:表示连接已经关闭或打开连接失败(CLOSED);

    我们可以通过判断这个值来执行我们相应的代码。

    除此之外,WebSocket对象还提供给我们一系列事件属性,使我们控制连接过程中的通信行为:

    • onopen:用于指定连接成功后的回调函数;
    • onclose:用于指定连接关闭后的回调函数;
    • onmessage:用于指定收到服务器数据后的回调函数;
    • onerror:用于指定报错时的回调函数;

    通过.send()方法,我们拥有了向服务器发送数据的能力(WebSocket还允许我们发送二进制数据):

    ws.send('Hi, server!')
    复制代码

    如何知道何时我们的数据发送完毕呢?我们需要使用WebSocket对象的bufferedAmount属性,该属性的返回值表示了还有多少字节的二进制数据没有发送出去,所以我们可以通过判断该值是否为0而确定数据是否发送结束。

    var data = new ArrayBuffer(1000000)
    ws.send(data)
    
    if (socket.bufferedAmount === 0) {
        // 发送完毕
    } else {
        // 还在发送
    }
    复制代码

    OK,目前为止我们花了大量篇幅解释了WebSocket协议是什么,它能够帮助我们做什么,以及客户端发送WebSocket请求的方式。但是目前为止,我们还是没有谈论一丁点关于WebSocket是如何帮助我们绕过浏览器的“同源策略”让我们实现“跨域资源共享”,你是否已经有点等的不耐烦了?

    但是别急,当你清楚的了解到WebSocket是什么之后,答案就呼之欲出了,那就是当客户端与服务端创建WebSocket连接后,本身就可以天然的实现跨域资源共享,WebSocket协议本身就不受浏览器“同源策略”的限制(还记得吧,同源策略只是限制了跨域的AJAX请求?),所以问题本身就不成立(有点赖皮是吧?)。

    但是你可能又会问,如果没有浏览器“同源策略”的限制,那么用户的Cookie安全又由谁来保护呢?问得好,看来你有认真阅读上面的文字,为了解答这个问题,让我们换一种角度思考,我们说过Cookie的存在就是为了给无状态的HTTP协议通讯添加状态,因为Cookie是明文传输的,且通常包含用户的身份信息,所以非常受到网络攻击者的“关注”。但是想想WebSocket协议下的通讯机制,客户端和服务端一旦建立连接,就可以顺畅的互发数据,因此WebSocket协议本身就是“有状态的”,不需要Cookie的帮忙,既然没有Cookie,自然也不需要“同源策略”去保护,因此其实这个问题也不成立。

    至此,已经将关于WebSocket的所有内容都大致讲述了一遍,真没想到是如此巨大的工作量。看来本篇文章不应该叫做“再也不学AJAX了”,而是“再也不学AJAX,JSONP,CORS,WebSocket..”。

    真是了不起。


    二、postMessage

    回头一看,我们已经在“跨域”这个主题上整整停留了三篇文章,涉及的技术包括JSONP,CORS与WebSocket。需要注意的是,以上这些跨域技术都只适用于客户端请求异域服务端资源的情景。而除此之外,有时候我们还需要在异域的两个客户端之间共享数据,例如页面与内嵌iframe窗口通讯,页面与新打开异域页面通讯。

    这就是使用HTML5提供的新API -- postMessage的时候了。

    使用postMessage技术实现跨域的原理非常简单,一方面,主窗口通过postMessageAPI向异域的窗口发送数据,另一方面我们在异域的页面脚本中始终监听message事件,当获取主窗口数据时处理数据或者以同样的方式返回数据从而实现跨窗口的异域通讯。

    让我们用具体的业务场景与代码进一步说明,假如我们的页面现在有两个窗口,窗口1命名为“window_1”, 窗口2命名为“window_2”,当然,窗口1与窗口2的“域”是不同的,我们的需求是由窗口1向窗口2发送数据,而当窗口2接收到数据时,将数据再返回给窗口1。先让我们看看窗口1script标签内的代码:

    // window_1 域名为 http://winodow1.com:8080
    window.postMessage("Hi, How are you!", "http://window2.com:8080")
    复制代码

    可以看到,postMessage函数接收两个参数,第一个为要发送的信息(可以是任何JavaScript类型数据,但部分浏览器只支持字符串格式),第二个为信息发送的目标地址。让我们再看看窗口2script标签内的代码:

    // window_2 域名为 http://window2.com:8080
    window.addEventListener("message", receiveMessage, false)
    
    function receiveMessage(event) {
        // 对于Chorme,origin属性为originalEvent.origin属性
        var origin = event.origin || event.originalEvent.origin
        if (origin !== "http://window1.com:8080") {
            return 
        }
        window.postMessage("I\'m ok", "http://window1.com:8080")
    }
    复制代码

    看到了吗,我们在window上绑定了一个事件监听函数,监听message事件。一旦我们接收到其他域通过postMessage发送的信息,就会触发我们的receiveMessage回调函数。该函数会首先检查发送信息的域是否是我们想要的(之后我们会对此详细说明),如果验证成功则会像窗口1发送一条消息。

    看起来很好懂不是吗,一方发送信息,一方捕捉信息。但是,我需要格外提醒你的是所有“跨域”技术都需要关注的“安全问题”。让我们想想postMessage技术之所以能实现跨域资源共享,本质上是要依赖于客户端脚本设置了相应的message监听事件。因此只要有消息通过postMessage发送过来,我们的脚本都会接收并进行处理。由于任何域都可以通过postMessage发送跨域信息,因此对于设置了事件监听器的页面来说,判断到达页面的信息是否是安全的是非常重要的事,因为我们并不想要执行有危险的数据。

    那么接下来的问题便是,如何鉴别发送至页面的信息呢?答案是通过 message事件监听函数的事件对象,我们称它为event,该对象有三个属性:

    • data:值为其他window传递过来的对象;
    • origin:值为消息发送方窗口的域名;
    • source:值为对发送消息的窗口对象的引用;

    很显然的,我们应该着重检测event对象的origin属性,建立一个白名单对origin属性进行检测通常是一个明智的做法。

    最后,再让我们谈谈postMessage对象的浏览器兼容性,这方面到是很幸运,除了IE8以下的IE浏览器,所有的浏览器都支持postMessage方法!


    至此,我们终于完全讲完了“跨域共享资源”这一主题。花了不少力气是吧?希望这是值得的。





    ? Hey!到这里《再也不学AJAX了!》这个专题系列就完全结束了,还记得我们的初心吗?我希望你能通过阅读这个系列的文章,以较为轻松的方式,系统完整地掌握AJAX技术,从此再也不用刻意学习零散的AJAX知识。希望我达成了我的目标,也希望你在阅读学习的过程中感到愉快。

    关于AJAX技术这个专题,其实我还想讲述的两个话题是:更优雅的资源获取方式:fetch API 以及 深入jQuery:AJAX的实现,但是鉴于我个人时间精力有限(完成一个系列文章真的比我想的要付出更多时间!),就决定暂时先放下,等将来有机会再以这个系列的番外篇的形式补充上去,希望你们可以理解和接受:)。

    这是我第一次在技术平台中以“系列”的方式发表技术文章,我个人觉得这样的方式更容易令人在整体上把握和理解一个技术,从而做到更灵活熟练的使用。希望你们也认同这一点并在阅读过程中感到愉快。之后,我也会继续在专栏中发表关于Web开发技术的系列文章,希望得到你们的认可和支持。

    最后,再谈谈我在技术平台发表文章的初心:之所以开始在各平台(目前为稀土掘金和segmentfault)发表技术文章,主要是为了帮助我消化知识,锻炼写作的文笔,验证我对某个技术的理解是否正确,以及积攒人气满足虚荣心。在这个过程中,也希望读者能够通过阅读我的文章,加深对某一技术的理解。我认为这是一件双赢的事情,因此我十分欢迎,甚至是期待你在阅读我任何文章的过程中都能够:

    1. 如果觉得有所收获,毫不犹豫的点击赞赏按钮(我真的真的会很开心?);
    2. 如果想到了其他相关知识,或发现我对某个技术的理解不正确,毫不犹豫的在评论区留言与我交流
    3. 如果对于我讲述中的某个概念还是不懂,毫不犹豫的在留言区告知我你的困惑,我会思考怎么样把这个概念讲述的更加清楚明白;
    4. 如果觉得我的文章不错,毫不犹豫的将我的文章推荐给他人,邀请他们成为我的读者;
    5. 如果你觉得阅读我的文章所花费的时间很值得,对你有很大帮助并且也认可我的劳动成果,你大可以点击下方红色的“赞赏支持”按钮为这篇文章付费,同时表达你对我创作的认可与支持。写作能够对人有益又能获得报酬,这着实令人倍感欣慰。

    我的创作和成长需要你们的帮助和支持,作为报答,我会持续发布优质的文章,陪同你们一起成长。关注我,一起加油吧! ?

    展开全文
  • 使用 CORS 跨域时,在 Ajax 请求时要自定义HTTP 的请求头 Origin,Origin 包含请求页面(当前页面)源信息——协议、域名和端口。比如: // ajax 中设置 HTTP 的请求头 Origin: http://www.test.net 服务器端...

    目录

    前言

    一、跨域

    1、跨域的产生

    二、解决跨域

    1、具备src的标签

    2、JSONP

    3、CORS

    4、WebSocket 协议(★★★★★)

    (1)、WebSocket 协议的特点

    (2)、WebSocket 协议客户端的 API

    5、postMessage(★★★★★)

    6、location.hash

    7、document.domain

    8、window.name

    三、其他

    1、反向代理

    2、只针对Chrome的跨域解决办法

    (1)、windows 操作系统

    (2)、MAC OS 操作系统

    四、对跨域的进一步学习


    前言

    一篇优秀的文章:https://www.cnblogs.com/best/p/6196202.html#_label2

     

    一、跨域

    1、跨域的产生

    同源策略:同协议、同域名、同端口。

    同源策略限制以下几种行为:

    • Cookie、LocalStorage 和 IndexDB 无法读取。
    • DOM 和 Js对象无法获得。
    • AJAX 请求不能发送。

    不遵守同源策略的通信就会产生跨域。

     

    二、解决跨域

    1、具备src的标签

    原理:所有具有src属性的HTML标签都是可以跨域的

    在浏览器中,<script><img><iframe><link>这几个标签是可以加载跨域(非同源)的资源的,并且加载的方式其实相当于一次普通的GET请求,唯一不同的是,为了安全起见,浏览器不允许这种方式下对加载到的资源的读写操作,而只能使用标签本身应当具备的能力(比如脚本执行、样式应用等等)。

    2、JSONP

    JSONP(JSON with padding,填充式 JSON 或参数式 JSON)看起来与 JSON 差不多,只不过是被包含在函数调用中的 JSON。

    callback({"name": "value"});

    JSONP 由两部分组成:回调函数 和 数据。回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON  数据。下面是一个典型的 JSONP 请求:

    http://freetest.net/json/?callback=handleResponse

    JSONP 的原理是:动态插入 <script> 标签,通过<script> 标签的 src 特性引入一个 js 文件,当这个 js 文件载入成功时会执行我们在 url 参数中指定的回调函数,并且会把我们需要的 json 数据作为参数传入。

    function handleResponse(res){
        console.log(res);
    }
    var script = document.createElement("script");
    script.src = "http://freetest.net/json/?callback=handleResponse";
    document.body.insertBefore(script, document.body.firstChild);

    优点是:兼容性好,简单易用,支持 浏览器与服务器之间的双向通信。

    缺点是:

    • 只支持 GET 请求。
    • JSONP 是从别的域加载代码执行,如果别的域不安全,很可能会在响应中夹带一些恶意的代码,而此时除了完全放弃使用 JSONP 调用之外,没有办法追究。
    • 要确定 JSONP 是否失败很麻烦,虽然 HTML5 给 <script> 元素新增了一个 error 事件处理程序,但目前没有得到任何浏览器的支持。为此开发人员不得不使用计时器检测指定的时间内是否接收到了响应。就算这样也不尽人意,毕竟不是每个用户上网的速度和宽带都一样。

    由于 JSONP 存在这样大的缺点,所以,现在已经没有使用 JSONP 的必要了,其他方法不能跨域的 JSONP 一样不能跨,其他方法要修改服务器端的 JSONP 一样要修改。

    3、CORS

    CORS(Cross-Origin Resource Sharing,跨域资源共享)定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。

    CORS 的基本思想是:使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是否成功。

    比如一个简单的使用 GET 或 POST 发送的  Ajax 请求,需要给它附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口)。以便服务器根据这个头部信息来决定是否给予响应。下面是 Origin 头部的示例:

    Origin: http://www.test.net

    如果服务器认为请求可以接受,就在 Access-Control-Allow-Origin 头部回发相同的源信息(如果是公共资源,可以回发 “*”)。例如:

    Access-Control-Allow-Origin:http://www.test.net

    如果没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。 

    【传送门:Ajax 的详细知识与案例,请戳:https://blog.csdn.net/mChales_Liu/article/details/106124912

    除 IE 之外的浏览器以及苹果和安卓都支持 XHR(XMLHttpRequest)类型对 CORS 的实现。IE8 中引入了 XDR(XDomainRequest)类型,用 XDR 实现了类似 XHR 的功能。因为不同浏览器对 CORS 的支持不一样,所以就有了跨浏览器的 CORS:

    function createCORSRequest(method, url){
        var xhr = new XMLHttpRequest();
        if("withCredentials" in xhr){// 检测是否支持 CORS
            xhr.open(method, url, true);
        }else if(typeof XDomainRequest != "undefined"){// 兼容 IE
            xhr = new XDomainRequest();
            xhr.open(method, url);
        }else{
            xhr = null;
        }
        return xhr;
    }
    
    var xhr = createCORSRequest("get", "http://www.test.net");
    if(xhr){
        xhr.onload = function(){
            // 对 xhr.responseText 进行处理
        }
        xhr.send();
    }

    Firefox、Safari 和 Chrome 中的 XHR 对象与 IE 中的 XDR 对象类似,都提供了够用的接口,他们共同的属性和方法如下:

    • responseText 属性:用于取得响应的内容。
    • abort() 方法:用于停止正在的请求。
    • send() 方法:用于发送请求。
    • error 事件:用于替代 onreadystatechange 检测错误。
    • load 事件:用于替代 onreadystatechange 检测成功。

    以上成员都包含在 createCORSRequest() 函数返回的对象中,在所有浏览器中都能正常使用。

     

    4、WebSocket 协议(★★★★★)

    HTTP 协议有一个缺陷:通信只能由客户端发起。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用“轮询”——每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。但是轮询的效率低,非常浪费资源。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

    Websocket 是 HTML5 新增的一种 “全双工通信协议”——客户端和服务端基于 TCP 握手连接成功后,两者之间就可以建立持久性的连接,实现双向数据传输。

    (1)、WebSocket 协议的特点

    • 建立在 TCP 协议之上,服务器端的实现比较容易。
    • 与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
    • 数据格式比较轻量,性能开销小,通信高效。
    • 可以发送文本,也可以发送二进制数据。
    • 没有同源限制,客户端可以与任意服务器通信。
    • 协议标识符是 ws(如果加密,则为wss),服务器网址就是 URL。
    ws://test.com
    wss://test.com

    只有支持 WebSocket 协议的服务器才能识别 ws 和 wss 标识符,才能正常工作。

    (2)、WebSocket 协议客户端的 API

    ①、用 WebSocket 构造函数创建它的实例

    WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例,参数是一个 URL(注意:HTTP 协议的 URL 可以相对可以绝对,但是 WebSocket 协议的 URL 必须是绝对路径)。

    var ws = new WebSocket('ws://localhost:8080');

    由于 WebSocket 协议 不受同源策略对的限制,所以,可以通过它访问任何站点的链接,至于是否会跨域通信,则完全取决于服务器。

    ②、建立 WebSocket 链接

    实例化 WebSocket 对象后,浏览器马上尝试创建连接,WebSocket 的实例上有一个 readyState 属性,该属性返回实例对象的当前状态,共有四种。

    • WebSocket.CONNECTING:值为 0,表示正在连接。
    • WebSocket.OPEN:值为 1,表示连接成功,可以通信了。
    • WebSocket.CLOSING:值为 2,表示连接正在关闭。
    • WebSocket.CLOSED:值为 3,表示连接已经关闭,或者打开连接失败。
    switch (ws.readyState) {
      case WebSocket.CONNECTING:
        // do something
        break;
      case WebSocket.OPEN:
        // do something
        break;
      case WebSocket.CLOSING:
        // do something
        break;
      case WebSocket.CLOSED:
        // do something
        break;
      default:
        // this never happens
        break;
    }

     ③、关闭 WebSocket 链接

    要关闭 WebSocket 链接,可以在任何时候调用 colse() 方法。调用了 close() 方法后,readyState 的值立即就会变成 2(正在关闭连接),而关闭连接之后就会变成 3。

    ws.close();

    ④、发送数据

    实例对象的 send() 方法用于向服务器发送数据。

    var ws = new WebSocket("ws://www.test.com/server.php");
    ws.send("Hello world");

    因为 WebSocket 协议只能发送纯文本数据,所以对于复杂的数据结构,发送之前都必须通过 JSON.stringify() 方法序列化,例如:

    var data = {
        name: "Mary",
        age: 18,
        say: function(){
            alert("hello");
        }
    }
    ws.send(JSON.stringify(data));

     ⑤、接收数据

    当服务器向客户端发来消息时,WebSocket 对象就会触发 message 事件,该事件把返回的数据保存在 event.data 属性中。

    ws.onmessage = function(event){
        var event = event || window.event;
        var data = event.data;
        // 处理数据
    }
    // 或者
    ws.addEventListener("message", function(event) {
        var event = event || window.event;
        var data = event.data;
        // 处理数据
    });

    实例对象的 message() 方法用于接收服务器返回的数据。

    ⑥、其他事件

    实例对象还有其他三个事件,在连接生命周期的不同阶段触发。

    • open 事件:在成功建立链接时触发。
    • error 事件:在发生错误时触发,连接不能持续。
    • close 事件:在连接关闭时触发。

    在这三个事件中,只有 close 事件的 event 对象有额外的信息。该事件的event对象有三个额外的属性:

    • wasClean 属性:是一个布尔值,表示连接是否已经明确地关闭。
    • code 属性:服务器返回的数值状态码。
    • reason 属性:是一个字符串,包含服务器发回的消息。

    可以把以上信息显示给用户,也可以记录到日志中以便将来分析。

    ws.onclose = function(event){
        console.log(`确定清除吗?${event.wasClean},服务器返回的状态码是${event.code},关闭的原因是${event.reason}`);
    }

    进一步学习 WebSocket,请看 阮老师的 WebSocket 教程:http://www.ruanyifeng.com/blog/2017/05/websocket.html

    关于 WebSocket 和socket 的区别请戳这里:https://www.cnblogs.com/zyy1688/p/10002089.html

    5、postMessage(★★★★★)

    postMessage() 方法是 HTML5 中新增的功能,用于跨文档消息传递(简称 XDM),

    由于我在之前的文章写过,所以恕不赘述,详情请戳:https://blog.csdn.net/mChales_Liu/article/details/106651864#%E4%B8%80%E3%80%81%E8%B7%A8%E6%96%87%E6%A1%A3%E6%B6%88%E6%81%AF%E4%BC%A0%E9%80%92

    6、location.hash

    实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

    具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。

    (1)、a.html:(http://www.domain1.com/a.html)

    <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
    <script>
        var iframe = document.getElementById('iframe');
    
        // 向b.html传hash值
        setTimeout(function() {
            iframe.src = iframe.src + '#user=admin';
        }, 1000);
        
        // 开放给同域c.html的回调方法
        function onCallback(res) {
            alert('data from c.html ---> ' + res);
        }
    </script>

    (2)、b.html:(http://www.domain2.com/b.html)

    <iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
    <script>
        var iframe = document.getElementById('iframe');
    
        // 监听a.html传来的hash值,再传给c.html
        window.onhashchange = function () {
            iframe.src = iframe.src + location.hash;
        };
    </script>

    (3)、c.html:(http://www.domain1.com/c.html)

    <script>
        // 监听b.html传来的hash值
        window.onhashchange = function () {
            // 再通过操作同域a.html的js回调,将结果传回
            window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
        };
    </script>

    7、document.domain

    此方案仅限主域相同,子域不同的跨域应用场景。

    实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

    (1)、父窗口:(http://www.domain.com/a.html)

    <iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
    <script>
        document.domain = 'domain.com';
        var user = 'admin';
    </script>

    (2)、子窗口:(http://child.domain.com/b.html)

    <script>
        document.domain = 'domain.com';
        // 获取父窗口中变量
        alert('get js data from parent ---> ' + window.parent.user);
    </script>

    8、window.name

    window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

    (1)、a.html:(http://www.domain1.com/a.html)

    var proxy = function(url, callback) {
        var state = 0;
        var iframe = document.createElement('iframe');
    
        // 加载跨域页面
        iframe.src = url;
    
        // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
        iframe.onload = function() {
            if (state === 1) {
                // 第2次onload(同域proxy页)成功后,读取同域window.name中数据
                callback(iframe.contentWindow.name);
                destoryFrame();
    
            } else if (state === 0) {
                // 第1次onload(跨域页)成功后,切换到同域代理页面
                iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
                state = 1;
            }
        };
    
        document.body.appendChild(iframe);
    
        // 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)
        function destoryFrame() {
            iframe.contentWindow.document.write('');
            iframe.contentWindow.close();
            document.body.removeChild(iframe);
        }
    };
    
    // 请求跨域b页面数据
    proxy('http://www.domain2.com/b.html', function(data){
        alert(data);
    });

    (2)、proxy.html:(http://www.domain1.com/proxy....
    中间代理页,与a.html同域,内容为空即可。

    (3)、b.html:(http://www.domain2.com/b.html)

    <script>
        window.name = 'This is domain2 data!';
    </script>

    总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

     

    三、其他

    1、反向代理

    反向代理的原理:受同源策略的限制,非同源的通信就会产生跨域,导致客户端直接与服务器通讯失败,于是另辟蹊径,可以在本地配置一个服务器(我自测采用的是Wampserver(PHP+Apache)),配置好反向代理后,直接访问本地服务器,本地服务器会去访问远程服务器,服务期间的通信没有跨域,所以就绕开了跨域,借助本地服务器成功返回了数据。

    反向代理学习资源大全:https://cloud.tencent.com/developer/information/js%E7%9A%84%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86

    2、只针对Chrome的跨域解决办法

    允许Chrome读写一个特定的文件夹。

    (1)、windows 操作系统

    ①、打开任务管理器,确保里面没有chrome 进程 

    ②、右键谷歌浏览器,"属性"中打开文件所在位置,进入浏览器安装文件夹

    ③、在文件位置栏中启动cmd命令行,输入chrome.exe,确定是否能启动浏览器。如果不能请检查自己浏览器文件的路径是否正确

    ④、 然后关掉chrome浏览器,通过在命令行输入chrome.exe --disable-web-security --user-data-dir 或 chrome.exe --args --disable-web-security --user-data-dir。

    ⑤、将指令“ --disable-web-security --user-data-dir” 或 “ --args --disable-web-security --user-data-dir”粘贴到这条下图的目标中,注意有空格,这两种方式都是一样的,直接粘贴这种其实就相当于系统打开谷歌时执行了“目标”里的指令而已。

    (2)、MAC OS 操作系统

    1⃣️、允许Chrome读写一个文件夹,比如:CCD。

    新建一个文件夹,作为允许chrome读写的文件夹,查看其路径。

    在terminal里运行以下命令:

    open -n /Applications/Google\ Chrome.app/ --args --disable-web-security  --user-data-dir=刚刚新建的文件夹的路径(我的是/Users/CCD)

    命令执行后,弹出窗口,提示如下图:

    点击启动即可开启一个新的网页,该网页已经可以读写CCD文件夹了。

    2⃣️、解决302报错

    再运行项目,可能会报错302(资源被重定向找不到了),怎么办呢?

    在浏览器地址栏输入并访问下面的网址:

    // chrome 浏览器的某些实验功能
    chrome://flags/

    ctrl+F 搜索:same-site-by-default-cookies,并将其设置为 disabled(禁用)。

    最后别忘了点击 relaunch哦。

     

    四、对跨域的进一步学习

    请戳此链接:https://segmentfault.com/a/1190000011145364

    展开全文
  • 1. 背景:由于公司前端页面部署在以https(加了证书)协议域名下,去请求http协议域名某个服务,并且该http域名下服务,不仅要处理普通请求POST、GET),还需要处理websocket请求。由于浏览器禁止https...

    1. 背景:由于公司前端的页面部署在以https(加了证书)协议的域名下,去请求http协议的域名的某个服务,并且该http域名下的服务,不仅要处理普通请求(POST、GET),还需要处理websocket请求。由于浏览器禁止https域名的内容请求http的服务,甚至嵌入子页面都禁止,因为浏览器会认为http的内容是不安全的,所以为解决该问题,研究出如下解决方案。

    2. 解决办法:由于浏览器禁止,但是服务器并不会禁止,所以,我在https的域名下,解析一台代理服务器,由该代理服务器去代替https去请求,再把结果返给前端。

    3. 开发环境:PyCharm,语言:Python3,服务框架:django

    4. 用到的库: pip3 install Django==1.11.3 django-cors-headers==3.2.1 dwebsocket==0.5.12 websocket==0.2.1 websocket-client==0.57.0

    5. settings.py配置:

    # 允许访问的host为所有
    ALLOWED_HOSTS = ['*']
    
    # 配置跨域请求问题
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_ALLOW_ALL = True
    
    CORS_ALLOW_METHODS = (
        'DELETE',
        'GET',
        'OPTIONS',
        'PATCH',
        'POST',
        'PUT',
        'VIEW',
    )
    CORS_ALLOW_HEADERS = (
        'XMLHttpRequest',
        'X_FILENAME',
        'accept-encoding',
        'authorization',
        'content-type',
        'dnt',
        'origin',
        'user-agent',
        'x-csrftoken',
        'x-requested-with',
    )
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        #'myapp.apps.MyappConfig',
        # 添加当前的app
        'myapp',
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        #  去除csrf校验
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    6. urls.py配置:

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url
    from myapp import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # 配置拦截/proxy 映射到 views.py中的方法
        url(r'^proxy$',views.proxy),
    ]
    

    7. views.py代码:仔细看注释

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    import requests
    from dwebsocket.decorators import accept_websocket
    import logging
    from websocket import create_connection
    import time
    
    #  设置日志格式
    LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
    DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
    fs = logging.StreamHandler()
    logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, handlers=[fs])
    #  Create your views here.
    
    # 添加dwebsocket的装饰器,该装饰器会对request属性添加websocket属性
    # 并添加 send()推数据  close()关闭连接  is_websocket()是否是websocket请求 等方法
    @accept_websocket
    def proxy(request):
        # 判断请求是否是websocket
        if not request.is_websocket():
            # 收到的请求的格式是  https://devlab.edu.huaweicloud.com/proxy?url=http://ip:8000/senddata?model=workload-read-mostly
            # 我们将这个服务部署到加了证书的服务器上,即可。
            # 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
            url = request.get_full_path().split('url=')[1]
            logging.info('proxy url : {}'.format(url))
            # 进行GET请求和POST请求的分别处理
            # if request.method == 'GET':
            #     logging.info('processing a url GET request !')
                # 其中省略了将请求的 header/cookie 传递给代理请求的 header/cookie ,由于我们业务不需要这些,我就不加了。
                # res = requests.get(url)
            # else:
            #     logging.info('processing a url POST request !')
            #     res = requests.post(url)
            # 由于我们的业务都是g GET 请求,所以就直接处理就好了
            res = requests.get(url)
            # 将代理请求的结果返回给真正的请求
            logging.info('revc : {}'.format(res.content.decode()))
            return HttpResponse(res.content.decode())
        else:
            # 收到的请求的格式是  wss://devlab.edu.huaweicloud.com/proxy?url=ws://ip:8000/senddata?model=workload-read-mostly
            # 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
            url = request.get_full_path().split('url=')[1]
            logging.info('proxy url : {}'.format(url))
            try:
                # 这里的header 必须要加上, 或者将 request中的header拿出来逐一存入list中,
                # 由于request中保存的headers的格式是dict,websocket中需要的headers是list,所以需要自行转化,
                # websocket的header的格式如下, 由于业务没有强制header 是什么,所以我就自己写的,但是注意,
                # 需要将以下的header的内容都要补充完整,否则会报 header...相关的错误,返回200或者其他状态码的错误,
                # 200在websocket是错误,在http里面是成功,需要注意一下。
                header = ['Accept-Encoding: gzip, deflate', 'Connection: Upgrade', 'Pragma: no-cache',
                          'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits',
                          'Sec - WebSocket - Version: 13',
                          'Upgrade: websocket',
                          'Access-Control-Allow-Origin: *',
                          'Access-Control-Allow-Headers: X-Requested-With',
                          'Access-Control-Allow-Methods: GET,POST,OPTIONS',
                          'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36']
                # 创建长连接/websocket
                ws = create_connection(url,header=header)
                # 每1秒就收一下消息
                while True:
                    # 接收消息,如果消息中带有Finished,表示消息都接收完毕,跳出循环。
                    res = ws.recv()
                    if 'Finished' in res:
                        logging.info('revc : {}'.format(res))
                        # 该服务,即作为服务端(接收并处理请求并响应方),又做为客户端(发送请求并接收另一个服务的响应)
                        # 所以将代理服务推过来的结果再推给浏览器
                        request.websocket.send(res)
                        # 调试的时候,浏览器端好像收不到最后一条消息,所以我在以这种方式再发送一遍吧
                        # return HttpResponse(res)
                        # websocket 相当占用网络资源,请及时关闭,由于生产环境中,网络资源的不稳定性,
                        # 可能数据还没推出去,就把websocket关闭了,会造成数据的丢失。
                        time.sleep(5)
                        ws.close()
                        request.websocket.close()
                        break
                    if not res == None:
                        logging.info('revc : {}'.format(res))
                        # 如果有数据, 将代理服务推过来的结果再推给浏览器
                        request.websocket.send(res)
                    time.sleep(1)
                # websocket 相当占用网络资源,请及时关闭,其实逻辑是走不到这里的,但是还是加上保险
                ws.close()
                request.websocket.close()
            except BaseException as e:
                logging.error(e)
    

    8. 部署 python3 manage.py runserver 0.0.0.0:8080

    展开全文
  • WebSocket简介

    2018-05-24 16:07:14
    1.定义 Websocket协议是一个持久化协议,建立在Tcp协议之上,无论是客户还是服务器,任何一端都可以执行主动关闭...请求方法常用有GET、HEAD、POST。每种方法规定了客户与服务器联系类型不同。由于HTTP协议简单...

    1.定义

        

    Websocket协议是一个持久化协议,建立在Tcp协议之上,无论是客户还是服务器,任何一端都可以执行主动关闭,通常情况是,客户执行主动关闭。


    2.与Http协议的比较

    协议Http协议Websocket协议

    简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
    (1)建立在 TCP 协议之上,服务器端的实现比较容易。

    2、灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

    3.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
    (3)数据格式比较轻量,性能开销小,通信高效。

    4.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
    (4)可以发送文本,也可以发送二进制数据。

    5、支持B/S及C/S模式。
    (5)没有同源限制,客户端可以与任意服务器通信。


    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
    ws:对应的是http请求

    wss:对应的是https请求


    3.Websocket请求与响应 

       3.1请求

    Sec-WebSocket-Protocol:
    一个Base64 encode的值,这个是浏览器随机生成的,用于验证是不是websocket服务器。
    Sec-WebSocket-Version:
    告诉服务器所使用的 Websocket Draft(协议版本),在最初的时候,Websocket协议还在 Draft 阶段,各种奇奇怪怪的协议都有,而且还有很多期奇奇怪怪不同的东西,什么Firefox和Chrome用的不是一个版本之类的,当初Websocket协议太多可是一个大难题。。不过现在现在已经确认为13。

    Upgrade:

        更新http协议为websocket协议

    3.2响应


    sec-websocket-accept
    这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key 。

    3.3错误情况

      如果服务器还是http服务器而非websocket服务器,将会创建websocket连接失败。

      


    4.详细介绍

     

    WebSocket构造函数接受一个必需和一个可选参数:
    WebSocket WebSocket(
      in DOMString url,
      in optional DOMString protocols
    );


    WebSocket WebSocket(
      in DOMString url,
      in optional DOMString[] protocols
    );
    url
    要连接的URL; 这应该是WebSocket服务器将响应的URL。
    protocols 可选的
    无论是单个协议字符串还是协议字符串数组。这些字符串用于指示子协议,以便单个服务器可以实现多个WebSocket子协议(例如,您可能希望一个服务器能够根据指定处理不同类型的交互protocol)。如果您不指定协议字符串,则假定为空字符串。
    构造函数可以抛出异常:
    SECURITY_ERR
    正在尝试连接的端口正在被阻止。
    方法概述
    void close(in optional unsigned long code, in optional DOMString reason);
    void send(in DOMString data);
    属性
    属性
    类型
    描述
    binaryType
    指示连接传输的二进制数据类型的字符串。如果Blob正在使用DOM 对象,则应该是“blob”,如果正在使用对象,则应该是“arraybuffer” ArrayBuffer
    bufferedAmount
    unsigned long
    已使用呼叫排队send()但尚未传输到网络的数据的字节数。一旦发送了所有排队的数据,该值就会重置为零。连接关闭时,该值不会重置为零; 如果你继续打电话send(),这将继续攀升。只读
    extensions
    服务器选择的扩展名。这当前只是由连接协商的空字符串或扩展列表。
    onclose
    在WebSocket连接readyState更改时调用事件侦听器CLOSED。监听者收到一个CloseEvent名为“close”的消息。
    onerror
    发生错误时要调用的事件侦听器。这是一个名为“error”的简单事件。
    onmessage
    从服务器收到消息时要调用的事件侦听器。监听者收到一个MessageEvent指定的“消息”。
    onopen
    在WebSocket连接readyState更改时调用事件侦听器OPEN; 这表示连接已准备好发送和接收数据。这个事件是一个简单的,名称为“open”的事件。
    protocol
    一个字符串,指示服务器选择的子协议的名称; 这将是protocols创建WebSocket对象时在参数中指定的字符串之一。
    readyState
    unsigned short
    连接的当前状态; 这是就绪状态常量之一只读。
    url
    由构造函数解析的URL。这永远是一个绝对的URL。只读。
    常量
    就绪状态常量
    这些常量由readyState属性用来描述WebSocket连接的状态。
    不变
    描述
    CONNECTING
    0
    连接尚未打开。
    OPEN
    1
    连接已打开并准备好进行通信。
    CLOSING
    2
    连接正在关闭。
    CLOSED
    3
    连接已关闭或无法打开。
    方法
    关()
    关闭WebSocket连接或连接尝试(如果有的话)。如果连接已经存在CLOSED,这个方法什么也不做。
    void close( 在可选的无符号短代码中, 在可选的DOMString原因中);
    参数
    code 可选的
    指示状态代码的数字值,说明连接关闭的原因。如果未指定此参数,则假定默认值为1005。查看页面上的状态代码列表以CloseEvent获取允许的值。
    reason 可选的
    一个可读的字符串,解释连接关闭的原因。该字符串不得超过123个字节的UTF-8文本(不是字符)。
    抛出异常
    INVALID_ACCESS_ERR
    code指定了无效。
    SYNTAX_ERR
    reason字符串过长或包含不成替代品。
    注意:在Gecko中,此方法在Gecko 8.0(Firefox 8.0 / Thunderbird 8.0 / SeaMonkey 2.5)之前不支持任何参数。
    发送()
    通过WebSocket连接将要传输的指定数据排入服务器,将值增加bufferedAmount包含数据所需的字节数。如果数据无法发送(例如,因为需要缓冲但缓冲区已满),则套接字会自动关闭。

    参数
    data
    要发送到服务器的数据。它可能是以下类型之一:
    一个文本字符串。该字符串以UTF-8格式添加到缓冲区,并且值bufferedAmount增加了表示UTF-8字符串所需的字节数。
    您可以发送由类型化数组对象使用的底层二进制数据; 其二进制数据内容在缓冲区中排队,将值增加bufferedAmount必要的字节数。
    指定Blob将blob的原始数据排入二进制帧中传输。该值将bufferedAmount增加该原始数据的字节大小。
    您可以将任何JavaScript类型的数组对象作为二进制框架发送; 其二进制数据内容在缓冲区中排队,将值增加bufferedAmount必要的字节数。
    抛出异常
    INVALID_STATE_ERR
    该连接目前不是OPEN
    SYNTAX_ERR
    数据是具有不成对代理的字符串。
    注意: Gecko的send()方法实现与Gecko 6.0中的规范有所不同; Gecko返回一个boolean指示连接是否仍然打开(以及扩展,数据已成功排队或传输); 这在Gecko 8.0中得到了纠正。
    从Gecko 11.0开始,支持ArrayBuffer被实现,但不支持Blob数据类型。

    展开全文
  • 处理网络请求的后台服务。适用于离线和后台同步数据或推送信息。不能直接和dom交互。通过postMessage方法交互。 Web Worker 模拟多线程,允许复杂计算功能脚本在后台运行而不会阻碍到其他脚本运行。适用于...
  • WebSocket Http上传

    2020-03-30 11:13:35
    C/C++ WebSocket 上传文件,主要是组装对于 HTTP 请求报文进行请求。想组装好这个Http报文可难可简单,这取决于经验。 // 请求方式 + URL + HTTP协议版本 url.append("POST " + "http://netaddress?arg1=***&...
  • 现在要测试这个推送名单是否正确,所以要用python写一个创建日程的post请求,指定参与者,即下面代码中的attendees。 开始写好代码的时候,没有添加参与人,即 "attendees": [],跑下来没毛病,日程创建成功! ...
  • okhttp是一个高性能http库,支持同步、异步请求,并且实现了spdy、http2、websocket协议,api比较简洁易用。 核心工具类: OkHttpClient:用于初始化http请求信息 Request:请求参数信息 Call:回调函数信息...
  • 浅谈websocket

    2017-02-15 19:35:13
    用户数多应用程序员,不怎么了解websocket,接下来我对websocket做一个简单介绍:http或者https大家都非常熟悉,开发app或者web应用时候,经常碰到场景是前端post或者get一个服务器请求,服务器返回数据给...
  • 取样器选择httprequest,请求方式一般是post的请求参数放到bodyData里 二、websocket协议 1.使用在线工具模拟websocket请求 在http://www.jsons.cn/websocket这个网站上连接ws:echo.websocket.org websocket...
  • 推大数据平台echarts等图表动态数据展示(用websocket实现实时数据刷新),首屏的数据加载是用的post从后台请求。 1.1 依赖 "axios": "^0.19.0", //用来封装自己的请求类API "countup.js": "^2.0.4", //数据大屏...
  • 客户端ajax调用 服务器通过 POST 全局变量 获取POST参数处理了请求后,如何将结果返回给客户端 有说用websocket,请问怎么获得用户端ip和端口呢?而且用户ip是局域网怎么办
  • 侦听127.0.0.1:8080的HTTP服务器,该服务器响应对路径'/'的POST请求。 # include " belle.hh " namespace Belle = OB::Belle; # include int main () { // init the server with local address
  • 前情概要: 使用SpringBoot及Construct2的WebSocket制作联机游戏(一) 一、介绍: ... 2、SpringBoot服务端WebSocket对接收数据和返回...3、Construct2客户端实现Get/Post请求并且显示返回数据 4、Construct2客户...
  • 1.首先实例化一个XHR对象, var xhr = new XMLHttpRequest(); 2.然后发动请求, ... open()方法第一个参数用于指定发送...”GET”和”POST”是得到广泛支持.参数还可以是”HEAD”、”OPTIONS”、”PUT”。第二个
  • webSocket入门demo

    2018-10-24 18:07:00
    若要上传图片之类插件需要实例化,请务必在post提交方法内实例化!!否则会多次请求 需要下载socket.io插件: npm install --save socket.io index.js /** * 用原生组件开启网络服务,用socket.io前后端交...
  • vue中使用websocket通信接收后台数据

    千次阅读 热门讨论 2019-08-20 16:52:45
    点击按钮后才开启websocket连接,然后发送数据给后端(相当于post请求中也是需要传递数据给后端使用),在websocket实例对象onmessage 函数中能获取到后端返回数据进行处理渲染。 2、代码...
  • 是Clojure事实上标准HTTP客户端。 这是一个出色库,但由于它基于 ,因此它也是一个很大依赖项。... 此函数接受三个参数(其中最后两个是可选):URL,请求和选项映射(有关详细信息,请参阅文档)。 GET请
  • 以前都是调取一个url接口,把结果post过去,然后接收post请求的那个函数,会把结果send到指定的websocket客户端,也可以是所有的websocket客户端。 但总是觉得频繁调用url,然后再send,觉得有些多此一举,还...
  • HTTP协议主要特点如下: 1)支持客户/服务器模式。...请求方法常用有GET、HEAD、POST。每种方法规定了客户与服务器联系类型不同。由于HTTP协议简单,使得HTTP服务器程序规模小,因而通信速度很快。 3
  • 4、post传递参数较大(有时会遇到使用get加请求参数,导致参数过长,被截断缺陷) 行业通用规范 无状态变化建议使用get请求 数据写入与状态修改建议用post Session Cookie Token区别 Session和Cookie使用:...
  • tcpcopy遇到websocket以后

    2021-01-09 23:16:24
    可以看到里面有\x00,\x81一堆不正常的请求。请问这个可能是什么原因呢? web服务器里面有http请求websocket,会不会是websocket导致? Thanks in advance.</p><p>该提问来源于开源项目:...
  • 关于Prince Fast&Light React SPA移动工具。 连接Redux。 webpack-dev-server提供热重载。 在本地主机(本地模式)...支持get,post,jsonp,webSocket模拟功能,支持在调试中请求本地主机使用命令use npm install p

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 214
精华内容 85
关键字:

websocket的post请求