'ReactJs Socket Client doesn't receive data from Flask Socket using emit(... , to=room)
I'm trying to develop a real-time chess app with Flask socket-io and ReactJs. My problem is that when setting emit(..., broadcast=True)
on the server-side, the front-end works fine and React can receive the data. However, I want to implement private chess data transferring via emit(..., to=room)
. I set the room name to the host session ID via request.sid
, however, nothing is transmitted as a result. Below is my code for the logic.
Thanks in advance
server.py
from flask import Flask, redirect, url_for, request, session
from flask_session import Session
from flask_socketio import SocketIO, send, emit, join_room, rooms
from config import ApplicationConfig
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
app.config.from_object(ApplicationConfig)
socketio = SocketIO(app, cors_allowed_origins='*', async_mode="eventlet")
server_session = Session(app)
#Set-up logging to ERROR only
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
#Change on deployment
app.host = 'localhost'
app.debug = True;
USERS={}
#------------------------- socket ----------------------------------------
@socketio.on('connect')
def connect(auth):
pass
# print("----------------------- | Connected | -----------------------------")
# print(f"User Connected with ID: {request.sid}")
# print("-------------------------------------------------------------")
@socketio.on('join')
def on_join(data):
if data['room']!="host":
join_room(USERS[data['room']]['sid'])
print(f"{request.sid} has joined room {USERS[data['room']]['sid']}")
send(f"Welcome to {request.sid}, {data['username']}", to=USERS[data['room']]['sid'])
else:
join_room(request.sid)
print(f"{request.sid} has joined room {request.sid}")
send( f"Welcome to {request.sid}, {data['username']}")
@socketio.on('connect-to-game')
def connect_to_game(payload):
try:
roomHost = payload['friendUsername']
userName = payload['username']
USERS[roomHost]["with"] = userName
USERS[roomHost]["withSid"] = request.sid
USERS[roomHost]["status"] = "in-game"
# Create the player object
USERS[userName] = {
"host" : USERS[roomHost]['sid'],
"status" : "in-game",
"sid" : request.sid,
"with" : roomHost,
"withSid": USERS[roomHost]["sid"],
}
if(USERS[roomHost]["side"] == "black"):
USERS[userName]["side"] = "white"
else:
USERS[userName]["side"] = "black"
# Sending data to the host
to_send = {
"host" : USERS[roomHost]['sid'],
"status" : "in-game",
"sid" : USERS[roomHost]["sid"],
"with" : userName,
"withSid" : request.sid,
"side" : USERS[roomHost]["side"]
}
# join_room(roomHost)
# print(f"{userName} has join room: {USERS[roomHost]['sid']}")
print(f"{to_send}")
# , room= to_send['host']
emit("connect-user", to_send, to=USERS[roomHost]['sid'])
return True
except:
return False
@socketio.on("create-user")
def onCreateUser(payload):
USERS[payload['username']] = {
"host" : request.sid,
"status" : "pending",
"sid" : request.sid,
"with" : "None",
"withSid": "None",
"side" : payload['side']
}
# join_room(request.sid)
# print(f"{payload['username']} has join room: {request.sid}")
# session['username']= payload['username']
@socketio.on('disconnect')
def disconnect():
pass
@socketio.on('message')
def handleMessage(msg):
print('Message: ' + msg)
send(msg, broadcast=True)
return None
@socketio.on("chess-move")
def handleChessMove(chessMoveData):
# room=USERS[chessMoveData['username']]['withSid']
print(f"{request.sid} is Sending data via room: {chessMoveData['host']}")
#, room=chessMoveData['host']
emit("update-chess-move", chessMoveData['move'], to=chessMoveData['host'])
#------------------------- app routing ------------------------------------
@app.route('/favicon.ico')
def favicon():
return redirect(url_for('static', filename='favicon.ico'))
@app.route('/api/user/<username>', methods=['GET'])
def get_user(username):
return USERS[username], 200
@app.route('/api/users', methods=['GET'])
def get_users():
return USERS, 200
if __name__ == "__main__":
socketio.run(app, port=5000)
create_game.jsx
import {useState, useEffect} from "react"
import configData from "../config.json"
import Link from 'next/link'
import io from "socket.io-client"
let socket = io.connect(configData.SOCKET_URL)
function createGame(){
const [username, setUsername] = useState("");
const [friendUsername, setFriendUsername] = useState("");
const [side, setSide] = useState("white")
useEffect(()=>{
// console.log(session);
}, [])
function connectToGame(){
socket.emit('join', {username: username,room:friendUsername})
socket.emit("connect-to-game", {
username: username,
friendUsername: friendUsername
});
}
function createGame(){
socket.emit("join", {username: username, room : "host"})
socket.emit("create-user", {username: username, side: side});
}
return(
<div>
<label htmlFor="userName">Your preferred username: </label>
<input
value={username}
type="text"
name="userName"
placeholder="Wonton Soup"
onChange={e => {setUsername(e.target.value)}}
/>
<br />
<br />
<label>
<input type="radio"
checked={side==="white"}
onChange={() =>{setSide("white")}}
name="side"/>
White
</label>
<br />
<label>
<input type="radio"
checked={side==="black"}
onChange={() =>{setSide("black")}}
name="side"/>
Black
</label>
<br />
<br />
<Link href={`/chess/${username}`}>
<button onClick={createGame} > Create A Game </button>
</Link>
<br />
<br />
<br />
<label htmlFor="friendName">Your friend already set up a game?? Join their game by their username</label>
<br />
<br />
<input
value={friendUsername}
type="text"
name="friendName"
placeholder="Corn Soup"
onChange={e => {setFriendUsername(e.target.value)}}
/>
<Link href={`/chess/${username}`}>
<button onClick={connectToGame} > Join Game </button>
</Link>
</div>
)
}
export default createGame;
chess/[id].jsx
import {useState, useEffect} from "react"
import * as ChessJS from "chess.js";
import dynamic from 'next/dynamic';
import {useRouter} from 'next/router'
import configData from "../../config.json"
import axios from 'axios'
import io from "socket.io-client"
let socket = io.connect(configData.SOCKET_URL)
const Chessboard = dynamic(() => import('chessboardjsx'), {
ssr: false
});
const Chessjs = typeof ChessJS === "function" ? ChessJS : ChessJS.Chess;
const game = new Chessjs();
function ChessGame(){
//------------------------- Chess States -------------------------------
const [fen, setFen] = useState("start");
const [history, setHistory] = useState([]);
const [currentSquare, setCurrentSquare] = useState("");
const [currentPieceSquare, setCurrentPieceSquare] = useState("");
//---------------------- Connection State ----------------------------
const [username, setUsername] = useState(useRouter().query.id);
const [gameState, setGameState] = useState({});
//-------------------- Chat States -------------------------------
const [chatLogs, setChatLogs] = useState (["Welcome to Player 1 and 2 to Chess"]);
const [message, setMessage] = useState("");
//-------------- Initial Talk to Server ----------------------------
useEffect(()=>{
async function fetchUserData(){
if(Object.keys(gameState).length === 0 && gameState.constructor === Object){
let response = await fetch(`${configData.FLASK_URL}/user/${username}`);
response = await response.json();
setGameState(response)
}
}
fetchUserData();
}, [])
useEffect(() =>{
socket.on("connect-user", connectRequest=>{
console.log("------------------------ connectRequest -----------------------");
console.log(connectRequest);
console.log("------------------------ --------------- -----------------------");
setGameState(connectRequest);
})
socket.on("update-chess-move", chessData =>{
let move = game.move({
from : chessData.from,
to: chessData.to,
promotion: "q"
})
if(move !== null){
setFen(game.fen());
setHistory(game.history());
}
})
}, [socket, game])
useEffect(()=>{
socket.open();
socket.on("message", msg=>{
setChatLogs([...chatLogs, msg]);
})
// return( ()=>{
// socket.close();
// })
}, [socket,chatLogs.length])
// UI Logic
function changeTextBox(e){
setMessage(e.target.value);
}
//When Send button is clicked
function onSendClick(){
//Send the message to the Flask Socket Server
if(message !== ""){
socket.emit("message", message);
setMessage("");
} else{
console.log("Bro Message can't be empty!!")
console.log(document.cookie);
}
}
// --------------------------- Chess Stuffs ---------------------------------------
function onDrop( {sourceSquare, targetSquare} ){
// Pass in an object with sourceSquare and targetSquare
console.log(`on Drop: from ${sourceSquare} to ${targetSquare}`);
let move = game.move({
from : sourceSquare,
to: targetSquare,
promotion: "q"
})
if(move !== null){
setFen(game.fen());
setHistory(game.history());
socket.emit("chess-move", {move: move, host : gameState.host});
}
}
function onSquareClick(square){
console.log("onSquareClick: " + square);
console.log(fen);
console.log(gameState);
};
function mouseOverSquare(square){
console.log(square);
}
return(
<div className="Chess">
<h1>Welcome: {username} </h1>
<h1>
{gameState.status}
</h1>
<div id="ChessBoard">
<Chessboard
onDrop={onDrop}
onSquareClick={onSquareClick}
position={fen}
mouseOverSquare={mouseOverSquare}
orientation={gameState.side}
/>
{history.map( move => <p key={move}>{move}</p>)}
</div>
<div id="ChatBox">
{
//Display chat logs
chatLogs.length > 0 && chatLogs.map((msg, index) => {
return(
<div className="chat-message" key={index}>
<p>{msg}</p>
</div>
)})
}
</div>
<input value={message} name="message" onChange={e => {changeTextBox(e)}}/>
<button onClick={onSendClick}>Send Message</button>
</div>
)
}
export default ChessGame;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|