最近看人家用socket.io聊天,于是自己也想打个服务试试,不试不知道,一试吓一跳,原来这里吗还有这么多坑,下面就是所遇的坑,记录一哈,但愿可以帮助到遇到同样的坑的小伙伴

一、服务端配置

这里我使用nodejs 作为我的后台服务

1、首先创建一个目录


D:\learnVUE>mkdir socketIOTest

2、再创建一个nodejs项目目录


D:\learnVUE>cd socketIOTest
D:\learnVUE\socketIOTest>mkdir nodejsProj

3、初始化一个nodejs项目


D:\learnVUE\socketIOTest>cd nodejsProj
D:\learnVUE\socketIOTest\nodejsProj>npm init -y

4、安装依赖


D:\learnVUE\socketIOTest\nodejsProj>npm i express -S
D:\learnVUE\socketIOTest\nodejsProj>npm i cors -S
D:\learnVUE\socketIOTest\nodejsProj>npm i socket.io -S

5、再在目录下新增一个app.js

在app.js中增加如下类容


/*
* @Descripttion:
* @version:
* @Author: dex
* @Date: 2021-01-21 18:01
* @LastEditors: dex
* @LastEditTime: 2021-01-21 18:01
*
*/
const app = require("express")();
var http = require("http").createServer(app);
var socket = require("socket.io")(http, {
transports: ["websocket"],
});
app.get("/", function (req, res) {
res.send("<h1>你好web秀</h1>");
});
//设置跨域访问
app.all("*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", " 3.2.1");
res.header("Content-Type", "application/json;charset=utf-8");
next();
}); // socket.on("connect", function (socket) {
// console.log("conneted ...", socket);
// }); // 监听客户端连接
socket.on("connection", function (socket) {
console.log("客户端有连接");
socket.on("connect", () => {
console.log("客户端开始连接");
});
// 监听客户端断开
socket.on("disconnect", () => {
console.log("客户端断开");
}); // 给客户端发送消息
socket.emit("welcome", "欢迎连接socket"); // 监听客户端消息
socket.on("hello", (data) => {
console.log("接收客户端发送数据", data);
});
});
// 启动服务器 监听 8088 端口
http.listen(3000, function () {
console.log("server runing at 127.0.0.1:3000");
});

6、运行测试


D:\learnVUE\socketIOTest\nodejsProj>node app.js
server runing at 127.0.0.1:3000

二、创建一个vue项目

1、创建一个vue目录


D:\learnVUE\socketIOTest> vue init webpack vueTestSocketIo

2、安装socket依赖


D:\learnVUE\socketIOTest\vueTestSocketIo>npm i vue-socket.io -S

3、修改main.js


import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import VueSocketIO from "vue-socket.io"; Vue.config.productionTip = false; // 注册
Vue.use(
new VueSocketIO({
debug: true, // debug调试,生产建议关闭
connection: "http://localhost:3000"
})
); new Vue({
// 这里为全局监听socket事件消息,监听函数这里只写了一点,其实很有很多事件。
sockets: {
connecting() {
console.log("正在连接");
},
disconnect() {
console.log("Socket 断开");
},
connect_failed() {
cosnole.log("连接失败");
},
connect() {
console.log("socket connected");
}
},
router,
render: h => h(App)
}).$mount("#app");

4、修改HelloWorld.vue


<template>
<div id="app55">
<div id="nav55">
<button @click="connect">建立连接</button>
<button @click="sendMessage">发送数据</button>
</div>
</div>
</template> <script>
export default {
data() {
return {};
},
methods: {
// 连接socket
connect() {
this.$socket.open(); // 开始连接socket
// 订阅事件
this.sockets.subscribe("welcome", data => {
console.log("welcome data==> ", data);
});
}, // 发送消息
sendMessage() {
this.$socket.emit("hello", "这里是客户端");
}
}, sockets: {
connect(data) {
console.log(data);
},
//
welcome: data => {
console.log("welcome data数据返回= >", data);
}
},
beforeDestroy() {
this.sockets.unsubscribe('welcome')
}
};
</script>

5、启动项目


D:\learnVUE\socketIOTest\vueTestSocketIo>npm run dev
I Your application is running here: http://localhost:8080

三、项目测试

满怀期待的启动项目,打开浏览器进行测试却得到了如下结果

想想是不是因为http的原因,那就试着将其部署到自己的https 服务器里面去,于是就开始着手下面的docker发布了

四、使用docker发布服务

1、配置Dockerfile

首选当然是把nodejs 项目搞到服务器,再配置一个Dockerfile这些都不多说了,可以看我另一篇docker发布vue

[root@dex nodejsProj]# ll
total 28
-rw-r--r-- 1 root root 707 Jan 22 06:20 app2.js
-rw-r--r-- 1 root root 1647 Jan 30 16:04 app.js
-rw-r--r-- 1 root root 581 Jan 22 10:00 Dockerfile
-rw-r--r-- 1 root root 1139 Jan 22 06:20 index.js
-rw-r--r-- 1 root root 452 Jan 22 09:57 package.json
drwxr-xr-x 2 root root 4096 Jan 22 06:20 public
drwxr-xr-x 2 root root 4096 Jan 22 06:20 views

其中Dockerfile类容也挺简单,就几行命令,看(这里要注意的是node镜像的版本不能太低))


FROM docker.io/node:12.19.0 # Create app directory
WORKDIR /usr/src/socketIoTestConnection # Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./ # configure npm source from taobao
#RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
RUN npm config set package-lock false
RUN npm install # If you are building your code for production
# RUN npm ci --only=production # Bundle app source
COPY . . EXPOSE 9019
CMD [ "npm", "start" ]

2、创建镜像


[root@dex nodejsProj]# docker build -t socketio_node_serve:v1 .
[root@dex ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
socketio_node_serve v1 53f997eed584 23 hours ago 930MB

3、创建容器


[root@dex nodejsProj]# docker run -p 8431:3000 --name socketio_serve -d socketio_node_serve:v
[root@dex nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f474d019a61d socketio_node_serve:v1 "docker-entrypoint.s…" 23 hours ago Up 23 hours 9019/tcp, 0.0.0.0:8431->3000/tcp socketio_serve

好了容器服务跑起来了,接下来是配置一个nginx 把我的容器端口映射到外网上去,让客服端来访问

五、配置nginx代理

在nginx 中最开始的配置时是这样的

    server {
listen 443 ssl; location /socketioserve/ {
proxy_pass http://localhost:8431/;
}
}

然后在页面修改连接地址来进行访问


// 注册
Vue.use(
new VueSocketIO({
debug: true, // debug调试,生产建议关闭
connection: "https://benpaodehenji.com/socketioserve"
})
);

发现根本就无法访问,于是找了一些资料,将其修改为如下配置


location /socket.io/{
proxy_pass http://127.0.0.1:8431;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}

六、跨域处理

发现是可以访问了,只是跨域的问题依旧存在

Access to XMLHttpRequest at 'https://benpaodehenji.com/socket.io/?EIO=4&transport=polling&t=NSiqHnZ' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.


failed: Error during WebSocket handshake: Unexpected response code: 502

使用官方方法检测

使用cmd 进行如下测试


C:\Users\Lenovo>curl https://benpaodehenji.com/socket.io/?transport=polling
{"code":0,"message":"Transport unknown"}

看这个结果发现是配置的问题,于是把app.js中


var socket = require("socket.io")(http, {
transports: ["websocket"],
});

修改为


var socket = require("socket.io")(http);

再度测试


C:\Users\Lenovo>curl https://benpaodehenji.com/socket.io/?transport=polling
0{"sid":"IXY8bzxMcCmwXunTAAAN","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
C:\Users\Lenovo>

发现配置已经和官方说的一样了,但是如下的跨域任然无法处理

在万般无奈下我单独创建了一个testConnectSocketio.html使用它来直接连接测试


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>testconnect</title> </head>
<body> <h6>test</h6>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.0/socket.io.js"></script>
<script language="JavaScript">
let socket = io('https://benpaodehenji.com',{
transports: ["websocket"]
});
socket.emit('hello', {msg:'hi, server'}); // socket.on()鐢ㄤ簬鎺ユ敹鏈嶅姟绔彂鏉ョ殑娑堟伅
socket.on('welcome', data=>{
console.log('client connect server',data);
});
socket.on('disconnect', ()=>{
console.log('client disconnect');
});
</script>
</body>
</html>

测试 客户端发起连接:

测试服务端响应:


2021-01-23T01:14:07.165041305Z > nodejsProj@1.0.0 start /usr/src/socketIoTestConnection
2021-01-23T01:14:07.165046213Z > node app.js
2021-01-23T01:14:07.165049447Z
2021-01-23T01:14:07.336723288Z server runing at 127.0.0.1:3000
2021-01-23T01:14:09.047098330Z 客户端有连接 2021-01-23T01:17:17.786180956Z 客户端断开
2021-01-23T01:24:49.561294438Z 客户端有连接
2021-01-23T01:24:49.624188505Z 接收客户端发送数据 { msg: 'hi, server' }

看上面的测试充分证明了我的服务端配置时ok的,但问题又出在哪里呢?

再回去看一次官网的处理方案,

于是再次将app.js中的配置


var socket = require("socket.io")(http);

修改为:


var socket = require("socket.io")(http, {
cors: {
origin: "https://benpaodehenji.com",
methods: ["GET", "POST"]
}
});

改完后删除容器,删除镜像,再重复上面第四步中的2、3步流程从头再来,希望这次可以成功…


测试

哎。这这这??

有回到官网,又发现了这一段:

于是赶紧配置

七、处理400异常

这次测试跨域提示已经没有了,但是测试又提示400错误


https://benpaodehenji.com/socket.io/?EIO=3&transport=polling&t=NTI4Tsg 400 (Bad Request)

于是到处收集资料,但是收获甚微…

A few days later…


再次回来测试项目,这次点击Network请求, 发现了如下错误

于是顺藤摸瓜,根据如上错误提示,最后在https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html
https://socket.io/blog/socket-io-3-1-0/发现了如下描述


这让我眼前一亮,是否发现了一棵救命稻草

说干就干,于是又在app.js增加 allowEIO3: true, 将配置修改如下


var socket = require("socket.io")(http, {
allowEIO3: true,
cors: {
origin: "http://localhost:8080",
methods: ["GET", "POST"],
credentials: true
}
});

再次生成镜像,运行容器测试…

终于看见了希望

这里还有一个要注意cors中的origin 不能配置为*,否者还是会提示如下跨域


Access to XMLHttpRequest at 'https://benpaodehenji.com/socket.io/?EIO=3&transport=polling&t=NTIIi9A' from origin 'https://localhost:8082' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

要配置为真实的客服端的IP

  cors: {
origin: "https://localhost:8080",
methods: ["GET", "POST"],
credentials: true
}

ok 看测试也可以接受客服端的数据了,这次踩坑经历基本结束。

最后最终修改好的app.js是这个样子的,谢谢阅读,希望可以为初次接触socketio的朋友提供一点帮助谢谢


/*
* @Descripttion:
* @version:
* @Author: dex
* @Date: 2021-01-21 18:01
* @LastEditors: dex
* @LastEditTime: 2021-01-30 18:45
*/
const app = require("express")();
var http = require("http").createServer(app);
var socket = require("socket.io")(http, {
allowEIO3: true,
cors: {
origin: ['http://localhost:8080', 'http://localhost:8082'],
methods: ["GET", "POST"],
credentials: true
}
});
app.get("/", function (req, res) {
res.send("<h1>你好web秀</h1>");
});
//设置跨域访问
app.all("*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", " 3.2.1");
res.header("Content-Type", "application/json;charset=utf-8");
next();
}); // socket.on("connect", function (socket) {
// console.log("conneted ...", socket);
// }); // 监听客户端连接
socket.on("connection", function (socket) {
console.log("客户端有连接");
socket.on("connect", () => {
console.log("客户端开始连接");
});
// 监听客户端断开
socket.on("disconnect", () => {
console.log("客户端断开");
}); // 给客户端发送消息
socket.emit("welcome", "欢迎连接socket"); // 监听客户端消息
socket.on("hello", (data) => {
console.log("接收客户端发送数据", data);
});
});
// 启动服务器 监听 8088 端口
http.listen(3000, function () {
console.log("server runing at 127.0.0.1:3000");
});

vue项目连接socket.io跨域及400异常处理的更多相关文章

  1. Vue项目在开发环境跨域和生成环境部署跨域问题解决

    一.在dev环境下的跨域问题解决1.项目使用的是axios请求网络,将baseUrl修改为/api (这里是使用webpack提供的代理功能将/api代理成目标接口host) axios.defaul ...

  2. Vue 项目中遇到的跨域问题及解决方法

    原文:https://www.jb51.net/article/137278.htm 问题描述 前端 vue 框架,跨域问题后台加这段代码 header("Access-Control-Al ...

  3. VUE前端项目配置代理解决跨域问题

    VUE前端项目配置代理解决跨域问题 问题如下,经常在本地调试接口出现这种问题 解决方式1:Chrome 的扩展插件 以前使用Chrome 的扩展插件,但是有时候还是会出现莫名其妙的问题. 需要梯子才行 ...

  4. 解决Django+Vue前后端分离的跨域问题及关闭csrf验证

      前后端分离难免要接触到跨域问题,跨域的相关知识请参:跨域问题,解决之道   在Django和Vue前后端分离的时候也会遇到跨域的问题,因为刚刚接触Django还不太了解,今天花了好长的时间,查阅了 ...

  5. nginx处理vue打包文件后的跨域问题

    起因 在vue文件打包后,项目脱离了vue配置的反向代理配置,还是会报跨域的错误,或者直接打不开本地文件, 但是此刻我们想打开打包后的文件,测试一下文件有没有错误,因为经常会存在开发阶段没有问题,打包 ...

  6. Grails项目开发——前端请求跨域问题

    Grails项目开发--前端请求跨域问题 最近做项目采用前后端分离的思想,使用Grails作为后台开发Restful API供前端调用. 在项目开发的过程中,遇到前端没办法通过ajax访问到后台接口的 ...

  7. .net , java webSocket 连接 Socket.io (1.4.4版本) 问题

    .net版Socketio4net类库和java版socket.io-java-client类库 连接socket.io 1.4版本都不行,网上大多是socket.io 0.9版本的,socket.i ...

  8. vue本地运行项目使用iframe的跨域问题

    1.获取iframe中的window对象 为了兼容大多数浏览器,应使用iframeElement.contentWindow来获取 https://blog.csdn.net/xiongzhengxi ...

  9. 从零开始学 Web 之 Vue.js(四)Vue的Ajax请求和跨域

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  10. VUE系列三:实现跨域请求(fetch/axios/proxytable)

    1. 在 config/index.js 配置文件中配置proxyTable 'use strict' // Template version: 1.3.1 // see http://vuejs-t ...

随机推荐

  1. Redis使用ZSET实现消息队列使用总结一

    转载请注明出处: 目录 1.zset为什么可以做消息队列 2.zset实现消息队列的步骤 3.使用jedis实现消息队列示例 4.+inf与-inf 5.redis使用list与zset做消息队列有什 ...

  2. 音频的价值、AI Codec 的意义与算法能力的边界丨一期一会 • 音频工程师专场

    前言 音频技术发展到今天,经历了从模拟音频到数字音频到历程.国际音频工程师协会创建于 1948 年,中国数字音频技术起步相对较晚,长期被国外组织和公司垄断.随着中国的不断发展.科技日益进步,经过近三十 ...

  3. 快速带你复习html(超详细)

    此内容包含: html基础 列表.表格 媒体元素 表单(重点) 1.HTML 基础 目标: 会使用HTML5的基本结构创建网页 会使用文本相关标签排版文本信息 会使用图像相关标签实现图文并茂的页面 会 ...

  4. ChatGPT|一文读懂GPT-4!

    前言 大家好,今天早上一早醒来,发现各大科技圈公众号平台开始刷屏OpenAI发布的新模型GPT4.0,看这个版本号就已经知道又是一大波特性的更新. 于是立马起来开始学习! GPT-4 发布视频(202 ...

  5. C# 通过StreamWriter输出的TXT流文件,前缀带EF BB BF

    好久没有动笔写博客了,这个小天地被我闲置的放了好久好久,接下来要慢慢捡起来了. 备注:通过C#的StreamWriter类输出一个TXT流文件,供下位机工程师使用,发现打开的16进制文件中,默认添加了 ...

  6. 论文解读(CosFace)《CosFace: Large Margin Cosine Loss for Deep Face Recognition》

    论文信息 论文标题:CosFace: Large Margin Cosine Loss for Deep Face Recognition论文作者:H. Wang, Yitong Wang, Zhen ...

  7. Android LineChart 折线图Demo

    1 首先在 build.gradle 里导入包 implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' 2.新建 启动Activity Li ...

  8. [J2EE:中间件]Slf4J+Logback快速入门

    1 简述 Logback The generic,reliable,fast & flexible Logging Framwork. 一款通用的.可靠的.快速的和灵活的日志框架. Logba ...

  9. 升级:In-Place Upgrade升级MySQL5.6.26

    升级需谨慎,事前先备份 MySQL升级的实质是对数据字典的升级,数据字典有:sys.mysql.information_schema.performance_schema . MySQL升级的两种方式 ...

  10. 【Vue】Vuex

    Vuex简介 概念: 专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中管理(读.写),也是一种适用于任意组件间的通信方式. 什么时候用Vuex ①多个 ...