一、什么是跨域?
指的是浏览器不能执行其他网站的脚本,简单来说是浏览器同源政策的限制,浏览器针对于ajax的限制。
同源政策
两个页面拥有相同的 协议,域名,端口 就是同源,如果有一个不相同就是不同源。
同源政策产生的目的
保护用户信息安全,防止一些网站盗取用户信息。
常见跨域场景
二、跨域解决方案
1、通过jsonp跨域
2、跨域资源共享(CORS)
3、document.domain + iframe跨域
4、location.hash + iframe
5、window.name + iframe跨域
6、postMessage跨域
7、nginx代理跨域
8、nodejs中间件代理跨域(非vue、vue(webpack--proxy代理))
9、WebSocket协议跨域
方案一:jsonp (json with padding)
原理:(回调函数)
1.动态创建一个script标签(无跨域限制)
2.通过srcipt标签里的src属性 进行 跨域访问 属性里面写 跨域的地址+ ?callback属性作为函数传递给后端
3.服务端通过接收客户端传过来的callback属性值对应的函数
4.要发生过去的数据 通过函数的参数传递过去 (JSON格式)
5.将函数名对应调用的执行代码返回给客户端(服务器端响应数据一定是函数代码的调用,当浏览器对script将响应内容加载完成后,会自动调用函数)
6.并且在服务器端的执行函数是字符串,字符串包裹着函数调用的代码,如果没有包裹,则就在服务端立即执行。
缺点:只能发送get请求,易受到 XSS攻击
客户端代码
// 1.封装一个jsonp函数; jsonp({ // method: 'GET',// 所有的jsonp请求都是get请求,所以这个属性可以不写了 // data: , // 写了以后太繁琐,取消 url: 'http://www.localhost:3006/api/jsonp', success: function (res) { console.log(res) } }) // 封装 function jsonp(obj) { // 1.创建一个script标签; 2.改变src 3.给函数起名字,定义为全局函数; var script = document.createElement("script"); // 不要用innerHTML, 他不会自动发送请求 // 3.给函数起名字,定义为全局函数; var fnName = "haha_123123"; // window.aaa就是把aaa设置为全局变量! window[fnName] = obj.success; // 2.改变src,添加到head中 script.src = obj.url + "?callback=" + fnName; // 把script标签添加到head标签中,就会发送src的请求了 document.head.appendChild(script); // 代码执行完毕,把script标签删除 script.onload = function () { document.head.removeChild(script); window[fnName] = undefined; } }
服务端代码
app.get("/api/jsonp", (req, res) => { // 获取函数名,设置对象,发送给客户端 const fnName = req.query.callback; // 定义发送给客户端的对象转换为json字符串 var objStr = JSON.stringify({ name: '张三', age: 18 }); // 字符串类型的执行函数 res.send(`${fnName}(${objStr})`); });
vue解决跨域问题- vue-jsonp
// 第一步:在vue项目中安装上vue-jsonp npm i vue-jsonp --save // 第二步:在vue项目中main.js导入 import { VueJsonp } from 'vue-jsonp' Vue.use(VueJsonp) // 使用示例: this.$jsonp(url, { id: '1', output: "jsonp" }).then(res => { console.log('res', res) }).catch(err => { console.log(err) })
方案二:CORS (CROSS-Origin Resource Sharing 跨域资源共享)
原理:服务器设置
同源政策默认阻止跨域获取资源,但是CORS给了web服务器权限,即服务器可以选择,允许访问他们的资源 。
CORS需要浏览器和服务器同时支持,才可以实现跨域请求,目前几乎所有浏览器都支持CORS,IE则不能低于IE10。CORS的整个过程都由浏览器自动完成,前端无需做任何设置,跟平时发送ajax请求并无差异。so,实现CORS的关键在于服务器,只要服务器实现CORS接口,就可以实现跨域通信。
缺点:忽略 cookie,浏览器版本有一定要求
属于跨源 AJAX 请求的根本解决方法。相比 JSONP 只能发GET
请求,CORS 允许任何类型的请求。
分类:简单请求和复杂请求
条件:
1、请求方式:HEAD、GET、POST
2、请求头信息:
Accept Accept-Language Content-Language Last-Event-ID Content-Type 对应的值是以下三个中的任意一个 application/x-www-form-urlencoded multipart/form-data text/plain
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
简单请求和复杂请求的区别:
简单请求:一次请求
复杂请求:两次请求,在发送数据之前会先发第一次请求做‘预检’,只有‘预检’通过后才再发送一次请求用于数据传输。
关于预检:
在发送真正的请求之前,会默认发送一个options请求,做预检,预检成功后才发送真正的请求。
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
实现:设置三个响应头
1.Access-Control-Allow-Origin 字段 (指定了哪些域名或ip地址可以跨域 也可以写* 代表允许所有地址;允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/')
response.setHeater('Access-Control-Allow-Origin',' http://XXX.cn || * || ip地址 ');
2.CORS默认支持9个请求头,如果在9个请求头之外 要单独设置,多个请求头之间要用英文逗号隔开。
// 提示OPTIONS预检时,后端需要设置的两个常用自定义头 response.setHeater('Access-Control-Allow-Headers','Content-Type,X-Requested-With');
3.默认情况下CORS仅支持客户端发起的GET、POST、HEAD请求,如果希望客户端发送PUT、DELETE请求需要在服务器端设置
response.setHeater('Access-Control-Allow-Method','PUT');
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示 response.setHeader("Access-Control-Allow-Credentials", "true");
和跨域CORS有关的几个请求头和响应头请求头
请求头 | 响应头 |
Origin | Access-Control-Allow-Origin |
Access-Control-Request-Headers | Access-Control-Allow-Headers |
Access-Control-Request-Method | Access-Control-Allow-Methods |
Access-Control-Allow-Credentials | |
Access-Control-Expose-Headers | |
Access-Control-Max-Age |
请求头:
- Origin:当前请求源,和响应头里的Access-Control-Allow-Origin 对标, 是否允许当前源访问,Origin是不可修改的
- Access-Control-Request-Headers:本次真实请求的额外请求头,和响应头里的Access-Control-Allow-Headers对标,是否允许真实请求的请求头
- Access-Control-Request-Method:本次真实请求的额外方法,和响应头里的Access-Control-Allow-Methods对标,是否允许真实请求使用的请求方法
响应头:
1.Access-Control-Allow-Credentials:
这里的Credentials(凭证)其意包括:Cookie ,授权标头或 TLS 客户端证书,默认CORS请求是不带Cookies的,这与JSONP不同,JSONP每次请求都携带Cookies的,当然跨域允许带Cookies会导致CSRF漏洞。如果非要跨域传递Cookies,web端需要给ajax设置withCredentials为true,同时,服务器也必须使用Access-Control-Allow-Credentials头响应。此响应头true意味着服务器允许cookies(或其他用户凭据)包含在跨域请求中。另外,简单的GET请求是不预检的,即使请求的时候设置widthCrenditials为true,如果响应头不带Access-Control-Allow-Credentials,则会导致整个响应资源被浏览器忽略。
2.Access-Control-Allow-Headers
3.Access-Control-Allow-Methods
4.Access-Control-Allow-Origin
5.Access-Control-Expose-Headers:
在CORS中,默认的,只允许客户端读取下面六个响应头(在axios响应对象的headers里能看到):
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
如果这六个以外的响应头要是想让客户端读取到,就需要设置Access-Control-Expose-Headers这个为响应头名了,比如Access-Control-Expose-Headers: Token
6. Access-Control-Max-Age:设置预检请求的有效时长,就是服务器允许的请求方法和请求头做个缓存。
补充:
根据头信息和请求方式,浏览器进行了优化,对请求进行划分,分为简单请求和非简单请求
简单请求和非简单请求不做概述
简单请求 : 满足浏览器请求会直接发送 并在请求头中携带Origin 表示本次来自哪个源
如果不满足简单请求 , 会在发送请求之前发送一个预检请求 大小为0kb 请求方式为options 收到服务器响应后,分析它是否支持跨域,如果支持跨域则直接发送,如果不支持 报错!
JSONP和CORS的区别:JSONP:服务端不用修改,需要改前端。发jsonp请求
JSONP:只能发GET请求
CORS:前端的代码不用修改,服务端的代码需要修改。如果是简单请求的话在服务端加上一个响应头。
CORS:可以发任意请求
方案三:document.domain + iframe跨域
此方案仅限主域相同,子域不同的跨域应用场景。
通过 iframe 是浏览器非同源标签,加载内容中转,传到当前页面的属性中。
实现原理:两个页面都通过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>
方案四: location.hash + iframe跨域
实现原理: 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>
方案五:window.name + iframe跨域
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从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
方案六:postMessage跨域
postMessage是HTML5 XMLHttpRequest Level 2中的 API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递
用法:postMessage(data,origin)方法接受两个参数
- data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
- origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
缺点:浏览器版本要求,部分浏览器要配置放开跨域限制
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'); iframe.onload = function() { var data = { name: 'aym' }; // 向domain2传送跨域数据 iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com'); // 接受domain2返回数据 window.addEventListener('message', function(e) { alert('data from domain2 ---> ' + e.data); }, false); </script>
2.)b.html:(http://www.domain2.com/b.html)
<script> // 接收domain1的数据 window.addEventListener('message', function(e) { alert('data from domain1 ---> ' + e.data); var data = JSON.parse(e.data); if (data) { data.number = 16; // 处理后再发回domain1 window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com'); } }, false); </script>
方案七:nginx 代理跨域(线上环境)
前端向发送请求,经过代理,请求需要的服务器资源
缺点:需要额外的代理服务器
1、nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location / { add_header Access-Control-Allow-Origin *; }
2、nginx反向代理接口跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
nginx具体配置:
#proxy服务器 server { listen 81; server_name www.domain1.com; location / { proxy_pass http://www.domain2.com:8080; #反向代理 proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 index index.html index.htm; # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用 add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为* add_header Access-Control-Allow-Credentials true; } }
1.) 前端代码示例:
var xhr = new XMLHttpRequest(); // 前端开关:浏览器是否读写cookie xhr.withCredentials = true; // 访问nginx中的代理服务器 xhr.open('get', 'http://www.domain1.com:81/?user=admin', true); xhr.send();
2.) Nodejs后台示例:
var http = require('http'); var server = http.createServer(); var qs = require('querystring'); server.on('request', function(req, res) { var params = qs.parse(req.url.substring(2)); // 向前台写cookie res.writeHead(200, { 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本无法读取 }); res.write(JSON.stringify(params)); res.end(); }); server.listen('8080'); console.log('Server is running at port 8080...');
方案八:Nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
1、 非vue框架的跨域(2次跨域)
利用 node + express + http-proxy-middleware 搭建一个proxy服务器。
1.)前端代码示例:
var xhr = new XMLHttpRequest(); // 前端开关:浏览器是否读写cookie xhr.withCredentials = true; // 访问http-proxy-middleware代理服务器 xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true); xhr.send();
2.)中间件服务器:
var express = require('express'); var proxy = require('http-proxy-middleware'); var app = express(); app.use('/', proxy({ // 代理跨域目标接口 target: 'http://www.domain2.com:8080', changeOrigin: true, // 修改响应头信息,实现跨域并允许带cookie onProxyRes: function(proxyRes, req, res) { res.header('Access-Control-Allow-Origin', 'http://www.domain1.com'); res.header('Access-Control-Allow-Credentials', 'true'); }, // 修改响应信息中的cookie域名 cookieDomainRewrite: 'www.domain1.com' // 可以为false,表示不修改 })); app.listen(3000); console.log('Proxy server is listen at port 3000...');
3.)Nodejs后台同(七:nginx)
2、 vue框架的跨域 -- Proxy代理(1次跨域,开发环境)
通过服务器代理去发ajax 这个代理是webpack提供给我们的 因为服务器只是对ajax的同源限制,并不会限制服务器之间的通信。
利用 node + webpack + webpack-dev-server 代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers 跨域信息了。
使用环境:开发环境
生产环境:nginx
webpack.config.js / vue.config.js 部分配置:
//vue.config.js module.exports = { entry: {}, module: {}, ... devServer: { proxy: { // 如果请求地址以/api打头,就出触发代理机制 // http://localhost:8080/api/login -> http://localhost:3000/api/login '/api': { // 拦截以 /api 开头的url接口 target: 'http://localhost:3000', //目标接口域名 路径:http://localhost:3000/api changeOrigin: true, //是否跨域 ws: true, //如果要代理 websockets,配置这个参数 secure: false, // 如果是https接口,需要配置这个参数 // // 标识替换 // // 原请求地址为 /api/getData 将'/api'替换''时, // // 代理后的请求地址为: http://xxx.xxx.xxx/getData // // 若替换为'/other',则代理后的请求地址为 http://xxx.xxx.xxx/other/getData pathRewrite: { // 标识替换 '^/api': '/' //重写接口 后台接口指向不统一 所以指向所有/ 路径:http://localhost:3000/ // '^/api': '/api/mock' } } }, }
方案九:WebSocket 协议跨域
- WebSocket protocol是HTML5一种新的协议(WebSocket协议本质上是一个基于tcp的协议)。
- 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,同时允许跨域通讯,是server push技术的一种很好的实现。
- Websocket是一个持久化的协议
WebSocket 的原理
- WebSocket约定了一个通信的规范,通过单个TCP一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
- 在WebSocket出现之前,web交互一般是基于http协议的短连接或者长连接
- WebSocket是一种全新的协议,不属于http无状态协议,协议名为"ws"
有什么用: WebSocket用来解决http不能持久连接的问题,因为可以双向通信所以可以用来实现聊天室,以及其他由服务端主动推送的功能例如 实时天气、股票报价、余票显示、消息通知等。
WebSocket与http的关系
相同点:
- 都是基于tcp的,都是可靠性传输协议
- 都是应用层协议
不同点:
- WebSocket是单个 TCP 连接上进行双向通信协议,模拟Socket协议,可以双向发送或接受信息
- HTTP是单向的
- WebSocket是需要浏览器和服务器一次握手进行建立连接的
- 而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接
联系:
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的
总结(总体过程):
首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。
WebSocket有以下特点:
- 是真正的全双工方式,建立连接后客户端与服务器端是完全平等的,可以互相主动请求。而HTTP长连接基于HTTP,是传统的客户端对服务器发起请求的模式。
- HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,信息交换效率很低。
Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别所以它需要对服务器和客户端都进行升级才能实现(主流浏览器都已支持HTML5)
var socket = new WebSocket("ws://example.com/socketserver"); socket.onopen = function(event) { socket.send("Hello server!"); }; socket.onmessage = function(event) { console.log("Received message from server: " + event.data); }; socket.onerror = function(event) { console.log("WebSocket error: " + event.error); }; socket.onclose = function(event) { console.log("WebSocket connection closed with code " + event.code); };
在上面的代码中,首先创建了一个 WebSocket 对象,指定了服务器的地址。然后在 onopen 回调函数中,发送了一个消息到服务器。当服务器发送消息到客户端时,onmessage 回调函数会被触发,从而可以处理服务器发送的消息。如果出现错误或者连接被关闭,onerror 和 onclose 回调函数会被触发,从而可以处理这些事件。
需要注意的是,在使用 WebSocket 发送消息之前,必须先建立 WebSocket 连接。在上面的代码中,通过创建一个 WebSocket 对象来建立连接,然后在 onopen 回调函数中发送消息到服务器。如果在连接建立之前就尝试发送消息,那么这些消息将无法发送成功。
vue怎么用websocket发送请求
<template> <div> <input v-model="message" @keyup.enter="sendMessage"> <button @click="sendMessage">Send</button> <ul> <li v-for="msg in messages">{{ msg }}</li> </ul> </div> </template> <script> export default { data() { return { message: '', messages: [], socket: null } }, created() { this.socket = new WebSocket('ws://localhost:3000') // 监听服务器端响应处理函数 this.socket.addEventListener('message', this.handleMessage) /* this.$once('hook:beforeDestroy',() => { // 关闭连接 this.socket.close() }) */ }, beforeDestroy() { // 关闭连接 this.socket.close() }, methods: { sendMessage() { // 向服务器端发送消息 this.socket.send(this.message) this.message = '' }, handleMessage(event) { this.messages.push(event.data) } } } </script>
在上面的代码中,
- 首先在 created 钩子函数中创建了一个 WebSocket 对象,并添加了一个消息处理函数 handleMessage。
- 在 sendMessage 方法中,将用户输入的消息发送到服务器。
- 在 handleMessage 方法中,将从服务器接收到的消息添加到 messages 数组中,从而可以在界面上显示出来。
- 在组件销毁之前,需要调用 close() 方法关闭 WebSocket 连接。
需要注意的是,在使用 WebSocket 时,需要考虑跨域问题。如果 WebSocket 连接的 URL 和当前页面的 URL 不同,那么需要在服务器端进行相应的跨域设置。同时,需要注意在发送和接收消息时的数据格式,通常需要将数据转换为 JSON 字符串进行传输也支持二进制。
原生WebSocket API 使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
缺点:浏览器一定版本要求,服务器需要支持 websocket 协议
1.)前端代码:
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script> <script> // var socket = io('http://www.domain2.com:8080'); // 创建Socket.IO实例,建立连接 var socket= new io.Socket('localhost',{ port: 8080 }); socket.connect(); // 连接成功处理 socket.on('connect', function() { console.log('Client has connected to the server!'); }); // 监听服务端消息 socket.on('message', function(msg) { console.log('data from server: ---> ' + msg); }); // 监听服务端关闭 socket.on('disconnect', function() { console.log('Server socket has closed.'); }); document.getElementsByTagName('input')[0].onblur = function() { // 通过Socket发送一条消息到服务器 socket.send(this.value); }; </script>
2.)Nodejs socket后台:
var http = require('http'); var socket = require('socket.io'); // 启http服务 var server = http.createServer(function(req, res) { res.writeHead(200, { 'Content-type': 'text/html' }); res.end(); }); server.listen('8080'); console.log('Server is running at port 8080...'); // 监听socket连接 socket.listen(server).on('connection', function(client) { // 接收信息 client.on('message', function(msg) { client.send('hello:' + msg); console.log('data from client: ---> ' + msg); }); // 断开处理 client.on('disconnect', function() { console.log('Client socket has closed.'); });