1.0IM客户端-组件通讯Call设计.
call算法实现:
call.js
export default class call {
constructor() {
}
static callDic={};
static addCallBack(type,callBack){
if (this.callDic[type]==null){
this.callDic[type]=[];
}
if (this.hasCallBack(type,callBack)==false){
this.callDic[type].push({"fun":callBack});
}
}
static hasCallBack(type,callBack){
if (this.callDic[type]==null){
return false;
}
for (var i=0;i<this.callDic[type].leading;i++){
if (this.callDic[type][i].fun==callBack){
return true;
}
}
return false;
}
static removeCallBack(evenType,callBack){
if(this.callDic[eventType]){
var index = this.getEventIndex(eventType,callBack);
if(index != -1){
this.callDic[eventType].aplice(index,i);
}
}
}
static getEventIndex(evenType,callBack){
if(!this.callDic[eventType]){
return -1;
}
for(var i=0;i < this.callDic[eventType].length;i++){
if(this.callDic[eventType][i].fun == callBack){
return i;
}
}
return -1
}
static dispatch(type,data){
if (this.callDic[type]){
var callFunc;
for (var fun in this.callDic[type]){
callFunc=this.callDic[type][fun];
callFunc.fun.call(callFunc.this,data);
}
}
}
}
2.0IM客户端-登陆后派发数据.
login/index.js
login() {
console.log(this.state.userName);
Call.dispatch('LoginInfo',{userId: 'makewheels',
userName: this.state.userName,
roomId: this.state.roomId,
roomName: 'r_'+this.state.roomId,
role: this.state.role
});
}
main绑定数据
componentDidMount(){
Call.addCallBack('LoginInfo',this.onLoginHandler.bind(this));
}
测试成功:
3.0IM客户端-登陆后派发数据.
main.js
onLoginHandler(data){
console.log(data);
this.setState({
isLogin:true,
hasUrlParams:false,
userId:data.userId,
userName:data.userName,
roomId:data.roomId,
roomName:data.roomName,
role:data.role,
});
}
onHangUpCallBack(){
}
getRequest(){
let url = location.search; //获取url中"?"符后的字串
let theRequest = new Object();
if (url.indexOf("?") != -1) {
let str = url.substr(1);
let strs = str.split("&");
for(let i = 0; i < strs.length; i ++) {
theRequest[strs[i].split("=")[0]]=decodeURI(strs[i].split("=")[1]);
}
}
return theRequest;
}
测试:
4.0IM客户端-登陆逻辑判断.
media/index.js
import React,{ Component, PropTypes} from 'react';
import css from './css/layout.css';
import Participant from './participants';
import Message from './chat/message';
import UserList from './users/index';
import Call from './call';
import Notify from './notify';
import ChatFeed from './chat/chatfeed';
let client = null;
let sessionId;
let userId;
let userName;
let roomId;
let roomName;
let role;
export default class VideoRoom extends Component{
constructor(params){
super(params);
this.state = {
users:[],
userId:params.userId,
userName:params.userName,
roomId:params.roomId,
roomName:params.roomName,
messages:[],
role:params.role,
};
}
componentDidMount(){
this.setState({
users:[],
userId:this.props.userId,
userName:this.props.userName,
roomId:this.props.roomId,
roomName:this.props.roomName,
messages:[],
role:this.props.role,
});
client = new WebSocket('wss://localhost:3002');
//连接
client.onopen = () =>{
console.log("wss connect success...");
this.register();
};
client.onmessage = (e) => {
var parsedMessage = JSON.parse(e.data);
console.info('Received message: ' + parsedMessage.type);
switch(parsedMessage.type){
case 'existingParticipants':
console.log('existingParticipants');
this.onExistingParticipants(parsedMessage);
break;
case 'newParticipantArrived':
console.log('newParticipantArrived');
this.onNewParticipant(parsedMessage);
break;
case 'participantLeft':
console.log('participantLeft');
this.onParticipantLeft(parsedMessage);
break;
case 'chat_public':
console.log("chat_public:" + parsedMessage.msg);
let arr = this.state.messages;
let uid = 1;
if(parsedMessage.userId == userId){
uid = 0;
}else{
uid = 1;
}
arr.push(new Message({id:uid,message:parsedMessage.msg,senderName:parsedMessage.userName}));
this.setState({
message:arr,
});
break;
default:
console.error('Unrecognized message',parsedMessage);
}
}
client.onerror = (e) => {
console.log('服务端返回消息onerror::' + e.data);
}
client.onclose = (e) => {
console.log('服务端返回消息onclose::' + e.data);
}
Call.addCallBack(Notify.ON_INPUT_MESSAGE,this.onInputMessage.bind(this));
}
componentWillUnmount(){
console.log('componentWillUnmount==================');
}
/**
* 注册并登录房间
*/
register(){
sessionId = this.getRandomUserId();
userId = this.state.userId;
userName = this.state.userName;
roomId = this.state.roomId;
roomName = this.state.roomName;
role = this.state.role;
var message = {
type:'joinRoom',
sessionId:sessionId,
userId:userId,
userName:userName,
roomId:roomId,
roomName:'demo',
role:role,
}
this.sendMessage(message);
}
onExistingParticipants(msg){
console.log(sessionId + " 登录成功");
var participant = new Participant();
participant.sessionId = sessionId;
participant.userId = userId;
participant.userName = userName;
participant.role = role;
const users = this.state.users;
users.push(participant);
this.setState({users:users});
msg.data.forEach(this.addParticipant.bind(this));
}
onNewParticipant(userSession){
this.addParticipant(userSession);
}
addParticipant(userSession){
var participant = new Participant();
participant.sessionId = userSession.sessionId;
participant.userId = userSession.userId;
participant.userName = userSession.userName;
participant.role = userSession.role;
const users = this.state.users;
users.push(participant);
this.setState({users:users});
console.log(this.state.users);
}
onParticipantLeft(request){
console.log('Participant ' + request.sessionId + ' left');
const users = this.state.users;
for(let u = 0; u < users.length; u++){
let item = users[u];
if(item.sessionId == request.sessionId){
users.splice(u,1);
break;
}
}
this.setState({users:users});
}
sendMessage(message){
console.log('Sending message:' + message.type);
if(client){
client.send(JSON.stringify(message));
}
}
//获取6位随机id
getRandomUserId(){
var num = "";
for(var i=0; i<6; i++){
num+= Math.floor(Math.random()*10)
}
return num;
}
onInputMessage(data){
console.log("SendMessage::" +data);
var message = {
type:'chat_public',
sessionId:sessionId,
userId:userId,
userName:userName,
roomId:roomId,
roomName:'demo',
msg:data,
}
this.sendMessage(message);
}
render(){
return(
<div style={{width:this.props.width?this.props.width:'100%',height:this.props.height?this.props.height:'100%',}} className={css.mainContainer}>
<iframe src={"./player/aliplayer.html?roomId=" + this.state.roomId} className={css.videoContainer}>
</iframe>
<div className={css.rightContainer}>
<div className={css.userListContainer}>
<UserList users={this.state.users}/>
</div>
<ChatFeed messages={this.state.messages}></ChatFeed>
</div>
</div>
);
}
}
VideoRoom.PropTypes = {
userId: React.PropTypes.string.isRequired,//用户id
userName: React.PropTypes.string.isRequired,//用户名
roomId: React.PropTypes.string.isRequired,//房间id
roomName: React.PropTypes.string.isRequired,//房间名称
role: React.PropTypes.string.isRequired,//角色
closeVideoRoom: React.PropTypes.func,//挂断视频房间
}
4.0IM客户端-聊天室设计.
新建目录
5.0IM客户端-前后端通讯方法.
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
socket抽象结构
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
聊天室通讯设计:
- socket连接
- 当前聊天室存在的用户下发
- 有新成员进入聊天室
- 有成员退出聊天室
- 有公共消息转发
5.0IM客户端-Socket连接处理.
持续更新中.