Commit 1900ab08 authored by Kim, Chaerin's avatar Kim, Chaerin
Browse files

server client socket 연결 완료

parent e8f19465
// express 설정 파일
import express from "express";
import cors from "cors";
import socketio from "socket.io";
import http from "http";
import wrtc from "wrtc";
import cookieParser from "cookie-parser";
import mainRouter from "./routes/index.js";
const app = express();
app.use(cors());
const server = http.createServer(app);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use("/api", mainRouter);
let receiverPCs = {};
let senderPCs = {};
let users = {};
let socketToRoom = {};
const pc_config = {
iceServers: [
// {
// urls: 'stun:[STUN_IP]:[PORT]',
// 'credentials': '[YOR CREDENTIALS]',
// 'username': '[USERNAME]'
// },
{
urls: "stun:stun.l.google.com:19302",
},
],
};
const isIncluded = (array, id) => {
let len = array.length;
for (let i = 0; i < len; i++) {
if (array[i].id === id) return true;
}
return false;
};
const createReceiverPeerConnection = (socketID, socket, roomID) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (receiverPCs[socketID]) receiverPCs[socketID] = pc;
else receiverPCs = { ...receiverPCs, [socketID]: pc };
pc.onicecandidate = (e) => {
//console.log(`socketID: ${socketID}'s receiverPeerConnection icecandidate`);
socket.to(socketID).emit("getSenderCandidate", {
candidate: e.candidate,
});
};
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
};
pc.ontrack = (e) => {
if (users[roomID]) {
if (!isIncluded(users[roomID], socketID)) {
users[roomID].push({
id: socketID,
stream: e.streams[0],
});
} else return;
} else {
users[roomID] = [
{
id: socketID,
stream: e.streams[0],
},
];
}
socket.broadcast.to(roomID).emit("userEnter", { id: socketID });
};
return pc;
};
const createSenderPeerConnection = (
receiverSocketID,
senderSocketID,
socket,
roomID
) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (senderPCs[senderSocketID]) {
senderPCs[senderSocketID].filter((user) => user.id !== receiverSocketID);
senderPCs[senderSocketID].push({ id: receiverSocketID, pc: pc });
} else
senderPCs = {
...senderPCs,
[senderSocketID]: [{ id: receiverSocketID, pc: pc }],
};
pc.onicecandidate = (e) => {
//console.log(`socketID: ${receiverSocketID}'s senderPeerConnection icecandidate`);
socket.to(receiverSocketID).emit("getReceiverCandidate", {
id: senderSocketID,
candidate: e.candidate,
});
};
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
};
const sendUser = users[roomID].filter((user) => user.id === senderSocketID);
sendUser[0].stream.getTracks().forEach((track) => {
pc.addTrack(track, sendUser[0].stream);
});
return pc;
};
const getOtherUsersInRoom = (socketID, roomID) => {
let allUsers = [];
if (!users[roomID]) return allUsers;
let len = users[roomID].length;
for (let i = 0; i < len; i++) {
if (users[roomID][i].id === socketID) continue;
allUsers.push({ id: users[roomID][i].id });
}
return allUsers;
};
const deleteUser = (socketID, roomID) => {
let roomUsers = users[roomID];
if (!roomUsers) return;
roomUsers = roomUsers.filter((user) => user.id !== socketID);
users[roomID] = roomUsers;
if (roomUsers.length === 0) {
delete users[roomID];
}
delete socketToRoom[socketID];
};
const closeRecevierPC = (socketID) => {
if (!receiverPCs[socketID]) return;
receiverPCs[socketID].close();
delete receiverPCs[socketID];
};
const closeSenderPCs = (socketID) => {
if (!senderPCs[socketID]) return;
let len = senderPCs[socketID].length;
for (let i = 0; i < len; i++) {
senderPCs[socketID][i].pc.close();
let _senderPCs = senderPCs[senderPCs[socketID][i].id];
let senderPC = _senderPCs.filter((sPC) => sPC.id === socketID);
if (senderPC[0]) {
senderPC[0].pc.close();
senderPCs[senderPCs[socketID][i].id] = _senderPCs.filter(
(sPC) => sPC.id !== socketID
);
}
}
delete senderPCs[socketID];
};
const io = socketio.listen(server);
io.sockets.on("connection", (socket) => {
console.log("socket connection complete")
socket.on("joinRoom", (data) => {
try {
let allUsers = getOtherUsersInRoom(data.id, data.roomID);
io.to(data.id).emit("allUsers", { users: allUsers });
} catch (error) {
console.log(error);
}
});
socket.on("senderOffer", async (data) => {
try {
socketToRoom[data.senderSocketID] = data.roomID;
let pc = createReceiverPeerConnection(
data.senderSocketID,
socket,
data.roomID
);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
await pc.setLocalDescription(sdp);
socket.join(data.roomID);
io.to(data.senderSocketID).emit("getSenderAnswer", { sdp });
} catch (error) {
console.log(error);
}
});
socket.on("senderCandidate", async (data) => {
try {
let pc = receiverPCs[data.senderSocketID];
await pc.addIceCandidate(new wrtc.RTCIceCandidate(data.candidate));
} catch (error) {
console.log(error);
}
});
socket.on("receiverOffer", async (data) => {
try {
let pc = createSenderPeerConnection(
data.receiverSocketID,
data.senderSocketID,
socket,
data.roomID
);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({
offerToReceiveAudio: false,
offerToReceiveVideo: false,
});
await pc.setLocalDescription(sdp);
io.to(data.receiverSocketID).emit("getReceiverAnswer", {
id: data.senderSocketID,
sdp,
});
} catch (error) {
console.log(error);
}
});
socket.on("receiverCandidate", async (data) => {
try {
const senderPC = senderPCs[data.senderSocketID].filter(
(sPC) => sPC.id === data.receiverSocketID
);
await senderPC[0].pc.addIceCandidate(
new wrtc.RTCIceCandidate(data.candidate)
);
} catch (error) {
console.log(error);
}
});
socket.on("disconnect", () => {
try {
let roomID = socketToRoom[socket.id];
deleteUser(socket.id, roomID);
closeRecevierPC(socket.id);
closeSenderPCs(socket.id);
socket.broadcast.to(roomID).emit("userExit", { id: socket.id });
} catch (error) {
console.log(error);
}
});
});
export default server;
This diff is collapsed.
...@@ -13,245 +13,24 @@ const Screen = () => { ...@@ -13,245 +13,24 @@ const Screen = () => {
const user = "00"; const user = "00";
let localVideoRef = useRef(null); let localVideoRef = useRef(null);
let sendPC;
let receivePCs;
// 방화벽 등의 보호장치를 거쳐 ip로 연결하기 위한 설정
const pc_config = {
iceServers: [
// {
// urls: 'stun:[STUN_IP]:[PORT]',
// 'credentials': '[YOR CREDENTIALS]',
// 'username': '[USERNAME]'
// },
{
urls: "stun:stun.l.google.com:19302",
},
],
};
useEffect(() => { useEffect(() => {
let newSocket = io.connect("/"); let newSocket = io("http://localhost:8080", {
newSocket.emit("connected", "채린이"); withCredentials: true,
newSocket.on("toclient", (data) => { extraHeaders: {
console.log(data.msg); "my-custom-header": "abcd"
});
}, []);
// useEffect(() => {
// let newSocket = io.connect("http://localhost:8080");
// let localStream;
// // console.log("newSocket", newSocket.id);
// //
// newSocket.on("userEnter", (data) => {
// console.log(data);
// createReceivePC(data.id, newSocket);
// });
// newSocket.on("allUsers", (data) => {
// let len = data.users.length;
// for (let i = 0; i < len; i++) {
// createReceivePC(data.users[i].id, newSocket);
// }
// });
// newSocket.on("userExit", (data) => {
// receivePCs[data.id].close();
// delete receivePCs[data.id];
// setUsers((users) => users.filter((user) => user.id !== data.id));
// });
// newSocket.on("getSenderAnswer", async (data) => {
// try {
// console.log("get sender answer");
// console.log(data.sdp);
// await sendPC.setRemoteDescription(new RTCSessionDescription(data.sdp));
// } catch (error) {
// console.log(error);
// }
// });
// newSocket.on("getSenderCandidate", async (data) => {
// try {
// console.log("get sender candidate");
// if (!data.candidate) return;
// sendPC.addIceCandidate(new RTCIceCandidate(data.candidate));
// console.log("candidate add success");
// } catch (error) {
// console.log(error);
// }
// });
// newSocket.on("getReceiverAnswer", async (data) => {
// try {
// console.log(`get socketID(${data.id})'s answer`);
// let pc = receivePCs[data.id];
// await pc.setRemoteDescription(data.sdp);
// console.log(`socketID(${data.id})'s set remote sdp success`);
// } catch (error) {
// console.log(error);
// }
// });
// newSocket.on("getReceiverCandidate", async (data) => {
// try {
// console.log(data);
// console.log(`get socketID(${data.id})'s candidate`);
// let pc = receivePCs[data.id];
// if (!data.candidate) return;
// pc.addIceCandidate(new RTCIceCandidate(data.candidate));
// console.log(`socketID(${data.id})'s candidate add success`);
// } catch (error) {
// console.log(error);
// }
// });
// setSocket(newSocket);
// navigator.mediaDevices
// .getUserMedia({
// audio: true,
// video: {
// width: 375,
// height: 260,
// },
// })
// .then((stream) => {
// if (localVideoRef.current) localVideoRef.current.srcObject = stream;
// localStream = stream;
// sendPC = createSenderPeerConnection(newSocket, localStream);
// createSenderOffer(newSocket);
// newSocket.emit("joinRoom", {
// id: newSocket.id,
// roomID: roomId,
// });
// })
// .catch((error) => {
// console.log(`getUserMedia error: ${error}`);
// });
// }, []);
const createReceivePC = (id, newSocket) => {
try {
console.log(`socketID(${id}) user entered`);
let pc = createReceiverPeerConnection(id, newSocket);
createReceiverOffer(pc, newSocket, id);
} catch (error) {
console.log(error);
}
};
const createSenderOffer = async (newSocket) => {
try {
let sdp = await sendPC.createOffer({
offerToReceiveAudio: false,
offerToReceiveVideo: false,
});
console.log("create sender offer success");
await sendPC.setLocalDescription(new RTCSessionDescription(sdp));
console.log(sdp, "", newSocket.id, "", roomId);
newSocket.emit("senderOffer", {
sdp,
senderSocketID: newSocket.id,
roomID: roomId,
});
} catch (error) {
console.log(error);
}
};
const createReceiverOffer = async (pc, newSocket, senderSocketID) => {
try {
let sdp = await pc.createOffer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
console.log("create receiver offer success");
await pc.setLocalDescription(new RTCSessionDescription(sdp));
console.log(sdp, newSocket.id, senderSocketID, roomId);
newSocket.emit("receiverOffer", {
sdp,
receiverSocketID: newSocket.id,
senderSocketID,
roomID: roomId,
});
} catch (error) {
console.log(error);
} }
};
const createSenderPeerConnection = (newSocket, localStream) => {
let pc = new RTCPeerConnection(pc_config);
pc.onicecandidate = (e) => {
if (e.candidate) {
console.log("sender PC onicecandidate");
newSocket.emit("senderCandidate", {
candidate: e.candidate,
senderSocketID: newSocket.id,
});
}
};
pc.oniceconnectionstatechange = (e) => {
console.log(e);
};
if (localStream) {
console.log("localstream add");
localStream.getTracks().forEach((track) => {
pc.addTrack(track, localStream);
}); });
} else { console.log(newSocket);
console.log("no local stream");
}
// return pc
return pc;
};
const createReceiverPeerConnection = (socketID, newSocket) => {
let pc = new RTCPeerConnection(pc_config);
// add pc to peerConnections object newSocket.emit("connected", "채린이");
receivePCs = { ...receivePCs, [socketID]: pc }; newSocket.on("toclient", (data) => {
console.log(data.msg);
pc.onicecandidate = (e) => {
if (e.candidate) {
console.log("receiver PC onicecandidate");
newSocket.emit("receiverCandidate", {
candidate: e.candidate,
receiverSocketID: newSocket.id,
senderSocketID: socketID,
}); });
}
};
pc.oniceconnectionstatechange = (e) => {
console.log(e);
};
pc.ontrack = (e) => { }, []);
console.log("ontrack success");
setUsers((oldUsers) => oldUsers.filter((user) => user.id !== socketID));
setUsers((oldUsers) => [
...oldUsers,
{
id: socketID,
stream: e.streams[0],
},
]);
};
// return pc
return pc;
};
return ( return (
<div className="container"> <div className="container">
{/* {console.log(users)} */}
<div className="mt-3" style={{ backgroundColor: "#FCF4FF" }}> <div className="mt-3" style={{ backgroundColor: "#FCF4FF" }}>
<div <div
className="m-2 d-flex fw-bold text-center" className="m-2 d-flex fw-bold text-center"
...@@ -277,9 +56,6 @@ const Screen = () => { ...@@ -277,9 +56,6 @@ const Screen = () => {
ref={localVideoRef} ref={localVideoRef}
autoPlay autoPlay
/> />
{/* {users.map((user, index) => {
return <Video key={index} stream={user.stream} />;
})} */}
</div> </div>
</div> </div>
); );
......
// express 설정 파일
import express from "express";
import cors from "cors";
import { Server } from "socket.io";
import http from "http";
import wrtc from "wrtc";
import cookieParser from "cookie-parser";
import mainRouter from "./routes/index.js";
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true,
},
});
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use("/api", mainRouter);
io.on("connection", (socket) => {
console.log("a user connected");
socket.on("connected", (data) => {
console.log(data);
});
socket.emit("toclient", { msg: "안녕하세요" });
});
export default server;
{ {
"watch": ["server"], "watch": ["."],
"ext": "js,jsx,json", "ext": "js,jsx,json",
"ignore": ["src/**/*.spec.js"], "ignore": ["src/**/*.spec.js"],
"exec": "node ./index.js" "exec": "node ./index.js"
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"cors": "2.8.5", "cors": "2.8.5",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"esm": "^3.2.25",
"express": "4.17.1", "express": "4.17.1",
"http": "0.0.1-security", "http": "0.0.1-security",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
...@@ -32,10 +31,11 @@ ...@@ -32,10 +31,11 @@
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"postgres": "^1.0.2", "postgres": "^1.0.2",
"sequelize": "^6.6.5", "sequelize": "^6.6.5",
"socket.io": "2.3.0", "socket.io": "^4.1.3",
"wrtc": "0.4.6" "wrtc": "^0.4.7"
}, },
"devDependencies": { "devDependencies": {
"@types/socket.io": "^3.0.2",
"nodemon": "2.0.7" "nodemon": "2.0.7"
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment