box-im即时通信聊天项目(部署&学习)

学习链接

box-im gitee代码 - 查看zzhua分支,application-zzhua配置文件

box-im 语雀文档

box-im 在线体验

box-im后台管理代码 - 还有个box-im后台管理哦

部署说明

效果

聊天消息

在这里插入图片描述
在这里插入图片描述

视频聊天

发起视频通话请求
在这里插入图片描述
收到视频通话
在这里插入图片描述
同意视频通话
在这里插入图片描述

语音聊天

在这里插入图片描述

目录

在这里插入图片描述

启动服务

需要启动下列服务

##
## 1、启动minio
##      MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=xxx nohup /boxim/minio/minio server /boxim/minio/data --console-address ":9001" --address ":9000" > /boxim/minio/log/minio.log 2>&1 &
##      需要配置为https访问,
##      参考: Linux系统下安装minio并设置SSL证书进行HTTPS远程连接访问:https://blog.csdn.net/qq_42623400/article/details/123844517、
##           新版MinIO安装,附带问题处理和SSL设置(巨详细):https://openatomworkshop.csdn.net/674015b6522b003a546de78a.html?
##           minio的安装以及配置https (docker部署):https://blog.csdn.net/weixin_51480428/article/details/129690529
##           设置minio 支持https访问:https://blog.csdn.net/weixin_39305029/article/details/122560654
## 2、启动redis
##    appendonly yes
##    appendfilename data.aof
##    dir /data
##    protected-mode no
##    bind 0.0.0.0
##    dbfilename dump.rdb
##    requirepass xxx
##
##    docker run -d -p 6379:6379 \
##            -v /boxim/redis/conf:/usr/local/etc/redis \
##            -v /boxim/redis/data:/data \
##            --name boxim-redis \
##            redis:6.0.8 redis-server /usr/local/etc/redis/redis.conf
##
## 3、启动mysql
##     docker run --rm --entrypoint=cat mysql:5.7 /etc/my.cnf > /boxim/mysql/conf/my.cnf
##
##     docker run \
##     --name boxim-mysql \
##     -p 3306:3306 \
##     --privileged=true \
##     -v /boxim/mysql/conf/my.cnf:/etc/my.cnf \
##     -v /boxim/mysql/data:/var/lib/mysql \
##     -e MYSQL_ROOT_PASSWORD=xxx \
##     -d mysql:5.7
##
## 4、启动coturn
##     /usr/local/coturn/bin/turnserver -o -a -f -c /usr/local/coturn/etc/turnserver.conf
##
## 5、启动im-server
##     nohup java -jar /boxim/imserver/im-server.jar > /dev/null 2>&1 &
##
## 6、启动im-platform
##     nohup java -jar /boxim/implatform/im-platform.jar > /dev/null 2>&1 &
##
## 7、启动nginx
##     /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
##     /usr/local/nginx/sbin/nginx -s reload

nginx.conf配置文件

有个问题:为什么前端dist下的img下的图片不能通过location / 的配置访问到,而是要通过单独配置1个location /img 才能访问到,而其它的dist下的js目录下的js文件也可以用location / 的配置访问到的。

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    
    client_max_body_size     50m;
    client_body_buffer_size  10m; 	  
    client_header_timeout    1m;
    client_body_timeout      1m;
    
    gzip on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_comp_level  4;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    gzip_vary on;
    
    
    server {
        listen       80;
        server_name  localhost;
        rewrite ^(.*)$	https://$host$1	permanent;
    }
    
    # HTTPS server
    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      /usr/local/nginx/cert/server.crt;
        ssl_certificate_key  /usr/local/nginx/cert/server.key;

        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        location / {
        
            ## root  /usr/local/nginx/html/meeting/dist;
            
            root   /boxim/imweb/dist;
            
            index  index.html index.htm;
                
            try_files $uri $uri/ /index.html;
        }   
        
        location /img {
            root /boxim/imweb/dist;
        }
        
        location ^~ /api/ {
            proxy_pass http://127.0.0.1:8888/;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    
        
        location /im {
       
           proxy_redirect off;
           
           # 如果location那里使用了正则表达式,则这里就不能写uri路径,就是端口后面不能写其它的了,否则校验不通过  
           proxy_pass http://127.0.0.1:8878;
           
           proxy_http_version 1.1;
           # 如果不配置这个 如果客户端一直不发送消息过来,经测试默认1分钟之后连接会关闭。所以需要心跳机制。
           proxy_read_timeout 36000s;
           proxy_send_timeout 36000s;
           
           # 升级协议头 websocket
           # 浏览器会携带Connection: UpgradeUpgrade: websocket;
           proxy_set_header Connection "Upgrade";
           proxy_set_header Upgrade $http_upgrade;
           
           # proxy_set_header Host $host;
           proxy_set_header X-Real_IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme; 
       }
        
    }
}

turnserver.conf

# 网卡名
relay-device=eth0
#内网IP
listening-ip=172.17.23.234
listening-port=3478
#内网IP,加密访问配置
relay-ip=172.17.23.234
tls-listening-port=5349
# 外网IP
external-ip=119.23.61.24
relay-threads=500
#打开密码验证
lt-cred-mech
cert=/usr/local/coturn/etc/turn_server_cert.pem
pkey=/usr/local/coturn/etc/turn_server_pkey.pem
min-port=49152
max-port=65535
#设置用户名和密码,创建IceServer时使用
user=zzhua:xxx
# 外网IP绑定的域名
realm=119.23.61.24
# 服务器名称,用于OAuth认证,默认和realm相同,部分浏览器本段不设可能会引发cors错误。
server-name=119.23.61.24
# 认证密码,和前面设置的密码保持一致
cli-password=xxx

流程分析

在这里插入图片描述

websocket.js

// 连上websocet之后, 发送1条登录信息, 确认登录成功之后然后开始发心跳, 
// 接收到心跳响应就隔一段时间再发1条心跳消息, 接收到其它消息则交给消息处理函数

var websock = null;

// 重连任务id
let rec; 

// 是否连上了websocket
let isConnect = false;

// 连上websocet并完成登录后的回调函数
let connectCallBack= null;
let messageCallBack = null;
let closeCallBack = null


let connect = (wsurl,accessToken) => {
	try {
		if (isConnect) {
			return;
		}
		console.log("连接WebSocket");
		websock = new WebSocket(wsurl); 
		websock.onmessage = function(e) {
			let sendInfo = JSON.parse(e.data)
			if (sendInfo.cmd == 0) {	
				heartCheck.start()
				// 登录成功才算真正完成连接
				connectCallBack && connectCallBack();
				console.log('WebSocket登录成功')
			} else if (sendInfo.cmd == 1) {
				// 重新开启心跳定时
				heartCheck.reset();
			} else {
				// 其他消息转发出去
				console.log("收到消息:",sendInfo);  
				messageCallBack && messageCallBack(sendInfo.cmd, sendInfo.data)
			}
		}
		websock.onclose = function(e) {
			console.log('WebSocket连接关闭')
			isConnect = false; //断开后修改标识
			closeCallBack && closeCallBack(e);
		}
		websock.onopen = function() {
			console.log("WebSocket连接成功");
			isConnect = true;
			// 发送登录命令
			let loginInfo = {
				cmd: 0,
				data: {
					accessToken: accessToken
				}
			};
			websock.send(JSON.stringify(loginInfo));
		}

		// 连接发生错误的回调方法
		websock.onerror = function() {
			console.log('WebSocket连接发生错误')
			isConnect = false; //连接断开修改标识
			reconnect(wsurl,accessToken);
		}
	} catch (e) {
		console.log("尝试创建连接失败");
		reconnect(wsurl,accessToken); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接
	}
};

//定义重连函数
let reconnect = (wsurl,accessToken) => {
	console.log("尝试重新连接");
	if (isConnect){
		//如果已经连上就不在重连了
		return; 
	}
	rec && clearTimeout(rec);
	rec = setTimeout(function() { // 延迟5秒重连  避免过多次过频繁请求重连
		connect(wsurl,accessToken);
	}, 15000);
};
//设置关闭连接
let close = (code) => {
	websock && websock.close(code);
};


//心跳设置
let heartCheck = {
	timeout: 5000, //每段时间发送一次心跳包 这里设置为20s
	timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)
	start: function() {
		if (isConnect) {
			console.log('发送WebSocket心跳')
			let heartBeat = {
				cmd: 1,
				data: {}
			};
			websock.send(JSON.stringify(heartBeat))
		}
	},

	reset: function() {
		clearTimeout(this.timeoutObj);
		this.timeoutObj = setTimeout(function() {
			heartCheck.start();
		}, this.timeout);

	}
};



// 实际调用的方法
let sendMessage = (agentData) => {
	if (websock.readyState === websock.OPEN) {
		// 若是ws开启状态
		websock.send(JSON.stringify(agentData))
	} else if (websock.readyState === websock.CONNECTING) {
		// 若是 正在开启状态,则等待1s后重新调用
		setTimeout(function() {
			sendMessage(agentData)
		}, 1000)
	} else {
		// 若未开启 ,则等待1s后重新调用
		setTimeout(function() {
			sendMessage(agentData)
		}, 1000)
	}
}

let onConnect = (callback) => {
	connectCallBack = callback;
}

let onMessage = (callback) => {
	messageCallBack = callback;
}


let onClose = (callback) => {
	closeCallBack = callback;
}
// 将方法暴露出去
export {
	connect,
	reconnect,
	close,
	sendMessage,
	onConnect,
	onMessage,
	onClose,
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值