ReactJS Browser Websocket Connection to SpringBoot Websocket - javascript

I'm trying to establish a websocket between a SpringBoot app at localhost:8090 and a React app at localhost:3000. Through Postman i'm able to establish a websocket connection and send/receive messages at localhost:8090/api/web-socket.
When I run the React app, the application loads but isn't able to establish the websocket connection to Springboot. I've tried the connection to both 127.0.0.1 and localhost with no luck. When I try to debug in the browser console I see the following error: "WebSocket connection to 'ws://localhost:8090/api/web-socket' failed:" notice there isn't any error details. The error location references line 28 of browser.js which is
else { native_instance = new NativeWebSocket(uri); }
Here is the full block:
function W3CWebSocket(uri, protocols) {
var native_instance;
if (protocols) {
native_instance = new NativeWebSocket(uri, protocols);
}
else {
native_instance = new NativeWebSocket(uri);
}
What is this error? How can I resolve it?
Here is the what the React code for establishing the socket connection:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {w3cwebsocket as W3CWebSocket} from "websocket";
import './index.css';
const client = new W3CWebSocket('ws://localhost:8090/api/web-socket');
export default class App extends Component{
onButtonClicked = (value) => {
client.send(JSON.stringify({
type: "message",
msg: value
}
));
}
componentDidMount() {
client.onopen = () => {
console.log('websocket client connected');
};
client.onmessage = (message) =>{
const dataFromServer = JSON.parse(message.data);
console.log("reply from socket server: ", dataFromServer);
}
}
render() {
return(
<div>
<button onClick={() => this.onButtonClicked("Example message from client to server")}>Send Message(start SAP)</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
UPDATE - RESOLVED
So after some further digging i discovered the issue was related to cross origin setting on the SpringBoot side. For anyone that runs into this issue in the future try the to add the following to your Socket configuration class:
.setAllowedOrigins("*")
In full it would look something like this:
registry.addHandler(new SocketTextHandler(), "/your-route").setAllowedOrigins("*");

Related

Emit Socket Io send event from diffrent files with SvelteKit Websocket implementation

I have followed this tutorial
https://joyofcode.xyz/using-websockets-with-sveltekit
and implemented a basic websocket server that sends a message to the client when he connects.
I want to also send a message when someone submits a form.
// socketIo.ts.js
import { Server } from 'socket.io';
let io
export function injectSocketIO(server) {
io = new Server(server);
io.on('connection', (socket) => {
socket.emit('eventFromServer', 'Hello, World 👋')
});
console.log('SocketIO injected');
}
export function send(sms){
io.emit('eventFromServer', sms);
}
export function getIO(){return io}
//vite.config.ts
import { sveltekit } from '#sveltejs/kit/vite';
import type { UserConfig } from 'vite';
import { injectSocketIO } from './socketIo.js';
import { Server } from 'socket.io'
const webSocketServer = {
name: 'webSocketServer',
configureServer(server) {
injectSocketIO(server.httpServer);
},
}
const config: UserConfig = {
plugins: [sveltekit(), webSocketServer]
};
export default config;
//my form action
import { send } from './socketIo.ts'
export const actions = {
default: async({ request }) =>{
console.log(send('da'))
I'm getting this error
Cannot read properties of undefined (reading 'emit')
TypeError: Cannot read properties of undefined (reading 'emit')
at Module.send (/home/runner/sveltekit-cpp/socketIo.ts:17:5)
at default (/home/runner/sveltekit-cpp/src/routes/+page.server.ts:10:16)
at call_action (file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/runtime/server/page/actions.js:204:9)
at handle_action_request (file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/runtime/server/page/actions.js:134:22)
at render_page (file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/runtime/server/page/index.js:65:26)
at async resolve (file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/runtime/server/index.js:247:17)
at async respond (file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/runtime/server/index.js:298:20)
at async file:///home/runner/sveltekit-cpp/node_modules/#sveltejs/kit/src/exports/vite/dev/index.js:418:22
I have tried exporting a send function from my socketIo file but it didn't work

socket io server connection fires multiple times

I am trying to create a basic game using next.js and node.js. When I run it I get multiple "connected" logs and when I check adapters -using io.sockets.adapter.rooms- I get even though there is just one client (One tab on chrome) connected:
io.sockets.adapter.rooms log:
Map(4) {
'tiTjbdGFj3EGgbwRAAAB' => Set(1) { 'tiTjbdGFj3EGgbwRAAAB' },
'DsCKvImAuh8H6Vr3AAAD' => Set(1) { 'DsCKvImAuh8H6Vr3AAAD' },
'FtJispkyF08rhHBDAAAF' => Set(1) { 'FtJispkyF08rhHBDAAAF' },
'PFO72' => Set(1) { 'FtJispkyF08rhHBDAAAF' }
}
app.js(server backend)
const app = require('express')();
const server = require('http').createServer(app);
const fs = require('fs');
const dirImage = './public/images';
const path = require( 'path' );
const io = require('socket.io')(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
}
});
server.listen(8000);
frontend react context socket connection:
import {createContext} from 'react';
import io from "socket.io-client";
export const socket = io("http://localhost:8000", {transports : ['websocket']});
export const SocketContext = createContext(socket);
Also creating socket variable in every page using useContext hook:
const socket = useContext(SocketContext);
When I run the server I still get 5 connections from one client
Connected!
Connected!
Connected!
Connected!
Connected!
What is the problem?
from your frontend app, you are using context api to connect socket but not using useEffect Hooks, So your connection line is running multiple time as how many time your app is re-rendering. I suggest to use useEffect hook with empty dependency array to run the connection only in first render.
I am attaching a sample code for you:
import io from "socket.io-client";
useEffect(() => {
socket = io.connect("http://localhost:8000");
return () => {
socket.disconnect();
};
}, []);
This will connect your socket connection first time and it will disconnect when the component ejects.
Should it be like this?
context file:
const SocketContext = createContext();
const SocketContextProvider = ({children}) =>{
const [socket,setSocket] = useState(null);
useEffect(()=>{
setSocket(io.connect("http://localhost:8000"));
},[]);
return (
// the Provider gives access to the context to its children
<SocketContext.Provider value={socket}>
{children}
</SocketContext.Provider>
);
}
export {SocketContext,SocketContextProvider}

Connecting React Native Socket.io-client with Python Server

I'm trying to connect a React Native client to the open Python server
The problem is that I read several resolutions on how to start a connection with the socket.io-client API, but nothing solves it.
It just doesn't connect. I will post the server and the client, and I have changed them several times.
Edit*1: The server side works, I tested it, using socket.io and python socket. But the client being React does not work
import React,{useState, useEffect} from 'react';
import { StyleSheet, Text, View, Pressable, Button } from 'react-native';
import socketIO from "socket.io-client";
export default class App extends React.Component {
constructor(props){
super(props)
this.state = {
string:"null",
chatMessage:"null",
chatMessages:[]
}
}
componentDidMount() {
this.socket = socketIO('192.168.0.107:15156')
this.socket.connect();
this.socket.on('connect', () => {
console.log('connected to socket server');
});
}
submitChatMessage(message) {
console.log(this.socket)
this.socket.emit('chat message', message);
this.setState({chatMessage: ''});
}
render() {
return (
<View style={{flex: 1,backgroundColor:'#000000', alignItems:'center', justifyContent:'center'}}>
<Button title="Start" onPress={()=>{this.submitChatMessage('connected')}}></Button>
</View>
);
}
}
Server
import socket
host = "192.168.0.107"
port = 15156
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
orig = (host, port)
tcp.bind(orig)
tcp.listen(1)
while True:
con, cliente = tcp.accept()
print ('Connected', cliente)
while True:
msg = con.recv(1024)
if not msg: break
print (cliente, msg)
print ('exiting', cliente)
con.close()
Edit*2: I tried to catch any error generated when connecting to the server, and simply created the socket object, without connecting to the server, not generating an error. How is this possible. There is no connection in the image and the object is created
componentDidMount() {
this.connectSocket()
}
connectSocket() {
try {
console.log("Connecting to the server...")
this.socket = io('http://192.168.0.107:15156',{autoConnect:false})
this.socket.connect()
console.log("Sucess");
}
catch (err){
console.log(err)
}
}
Edit*3
I was able to detect an error when using this,
this.socket.on("connect_error", (err) => {
console.log(err)
})
// [Error: xhr poll error] //Looping
The point is, it could have been better not to have found it.
Any way forward?
I just forgot to connect the android on the network, third day for that

Angular Node | SocketIO | Event not emitted from node

I had asked this question before but here's a simple code for the same.
Im sending the data to Node from angular via websocket but I don't get the emitted event:
I've followed 10+ tutorials and forums, newest from here: https://www.youtube.com/watch?v=66T2A2dvplY&t=317s
service:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { io } from 'socket.io-client';
#Injectable({
providedIn: 'root'
})
export class SocketService {
socket = io('ws://localhost:3000'); // adding 'http://localhost:3000' also doesnt work
constructor() {}
listen(eventName: string) {
return new Observable( subscriber => {
this.socket.on(eventName, data => {
subscriber.next(data);
});
});
}
emit(eventName: string, data) {
this.socket.emit(eventName, data);
}
}
from component's ngOnInit(), this is called:
this._socketService.listen('test event').subscribe( data => {
console.log("data from server: ", data);
});
server code of Node:
const app = require('./app');
const port = process.env.PORT || 3000;
const server = require('http').createServer(app);
const socketio = require('socket.io');
const io = socketio(server,
{
serveClient: true,
pingInterval: 60000,
pingTimeout: 60000000,
cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"],
credentials: true
}
});
io.on('connection', function (socket) {
console.log("A user connected ", socket.connected); // works till here for every ping interval
socket.emit('test event', 'here is some data'); // this is either not executed or doesn't work
});
server.listen(port);
socket.connected is always true in NODE server, but false in Angular
What Ive tried:
CORS has been suppressed, I hope that's not the issue cuz nothing is seen like so
changing io.('connection' ...) to io.connect('connect'...)
init this.socket = io(...) in constructor
There is no data exchange seen in Network or Network > WS tab in case I emit from Angular too
This is my 3rd day with this problem, I'll highly appreciate any help.
Thank you
your mixing protocols from client.
change
socket = io('ws://localhost:3000');
to
socket = io('http://localhost:3000', { withCredentials: true });
As mentioned in introduction under chapter What Socket.IO is not that socket.io is not a pure WS lib.

NUXT (SSR Mode) connect Lavarel Pusher Socket

I want to connect the Laravel Pucher Socket to NUTX.js ( SSR Mode) Application.
Above code add-in socket socketio.js plugins file. this code not working.
Anyone tell me what's wrong.
How to connect Socket in NUXT SSR mode.
import Echo from "laravel-echo";
import config from "../config/config.global";
export default async ({ store, $axios }) => {
const port = 6001;
window.io = require("socket.io-client");
window.Pusher = require("pusher-js");
console.log(typeof io, "socketIO");
if (typeof io !== "undefined") {
// connect to web socket
try {
window.Echo = new Echo({
broadcaster: "pusher",
key: config.secretKey,
wsHost: config.socketUrl,
wsPort: port,
disableStats: true,
auth: {
headers: config.header
}
});
console.log("connect to socket");
} catch (error) {
console.log(error.message);
}
}
function listenStock({ channelName, eventName }, callback) {
console.log("callback",callback);
window.Echo.channel(channelName).listen(eventName, callback);
}
// Get user Balance Socket
listenStock(
{
channelName: `BalanceUpdateEvent.${store.getters.GetUserUUID}`,
eventName: "BalanceUpdateEvent"
},
({ data }) => {
try {
console.log(data,"Data");
} catch (ex) {
console.log(ex);
}
}
);
};
In Nuxt have two Mode SPA and SSR.
SPA run only client side
SSR run Client and Server Side.
So i created repositories about laravel echo socket pusher service connect to NUXT Mode.
NUXT (SSR Mode):
https://github.com/mankarsandesh/nuxt-socket-laravel-echo-SSR
NUXT (SPA Mode)
https://github.com/mankarsandesh/nuxt-socket-laravel-echo-SPA

Categories