Search code examples
reactjsnginxwebsocketsocket.iochat

ERR_CONNECTION_REFUSED in Socket.IO


I'm currently using Socket.IO and React to create a chat, but I can't connect to my server because the connection is being refused. I tried using different IP in CORS ORIGIN (and using ['*']), tried using newSocket = io('localhost:4444');, tried using newSocket = io('my domain with reverse proxy to port 4444');, the only way it works is using the numerical ip of my vm newSocket = io('195.XXX.XX4:4444');.

What can I try next?

My frontend is hosted in port 3000, and the socket in 4444.

React-frontend:

let newSocket;

try {
  newSocket = io.connect('http://localhost:4444');
} catch (e) {
  console.log(e);
  window.location.reload();
}

setSocket(newSocket);

return () => {
  newSocket.disconnect();
};`

Socket.IO code (btw the comments are in pt-br):

const express = require('express');
const mongoose = require('mongoose');
const http = require('http');
const socketIo = require("socket.io");
const Chat = require('./models/Chat.js');
const dotenv = require("dotenv");
const cors = require('cors'); // Importe a biblioteca CORS

const app = express();
app.use((req, res, next) => {
    res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' https://www.googletagmanager.com https://cdnjs.cloudflare.com 'unsafe-inline'; font-src 'self' https://fonts.gstatic.com;");
    next();
});

dotenv.config();

const port = process.env.PORT || 3000;
const server = http.createServer(app);
const io = socketIo(server, {
  cors: {
    origin: ['http://localhost:3000'],
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization'],
    credentials: true,
  },
  debug: true,
});


// Use a biblioteca CORS como middleware
app.use(cors({
  origin: ['http://localhost:3000'],
  methods: ['GET', 'POST', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
}));

mongoose.connect(`mongodb+srv://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@yc-cluster.bn5qm0z.mongodb.net/socketio`, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
.then(() => {
  console.log('Connected to MongoDB Atlas');
})
.catch((err) => {
  console.error('Error connecting to MongoDB Atlas:', err);
});

const chatRoutes = require('./routes/chatRoutes');
app.use(express.json());
app.use('/api', chatRoutes);

// SOCKET DE CONEXÃO


io.on('connection', (socket) => {
  socket.on("connect_error", (err) => {
    console.log(`connect_error due to ${err.message}`);
  });
  console.log('User connected in socket');
  socket.on('join chat', (id_do_clube) => {
    const { id_club } = id_do_clube;
    const chatRoom = 'chat_' + id_club; 
    socket.join(chatRoom);
    console.log('User connected in chat room: ' + 'chat_' + id_club);

    socket.on('disconnect', () => {
      console.log('User disconnected');
    });

    // SOCKET DE ENVIO DE MENSAGENS
    socket.on('chat message', async (message) => {
      
      // Salvar a mensagem no banco de dados
      const chat = new Chat({
        sender: message.sender,
        message: message.message,
        id_club: message.id_club,
        id_user: message.id_user,
        sender: message.sender,
        sender_image: message.sender_image,
        announcement: message.announcement,
        type: message.type,
        role: message.role,
      });
      try {
        const newChat = await chat.save();
        socket.emit('chat message', newChat);
        io.to(chatRoom).emit('chat message', newChat);
        socket.emit('chat message response', "Mensagem enviada com sucesso");
      } catch (err) {
        console.error('Error saving chat message:', err);
      }
    });

    socket.on('get old messages', async (id_club) => {
      try {
        const oldChats = await Chat.find({ id_club }).sort({ timestamp: 'asc' });
        socket.emit('old messages', oldChats);
      } catch (err) {
        console.error('Error retrieving old messages:', err);
      }
    });

    // SOCKET DE EDIÇÃO DE MENSAGENS
    socket.on('edit message', async (editedMessage) => {
      try {
        const { messageId, newMessage, id_user } = editedMessage;
        const chat = await Chat.findById(messageId);
    
        if (!chat) {
          console.error('Mensagem não encontrada');
        }
    
        if (parseInt(chat.id_user) !== parseInt(id_user)) {
          console.error('Usuário sem permissão de editar a mensagem');
        }
    
        const updatedChat = await Chat.findByIdAndUpdate(
          messageId,
          { message: newMessage, edited: true },
          { new: true }
        );
    
        // Emitir evento para informar que deu certo para o cliente
        socket.emit('message edited response', "Mensagem editada com sucesso");
        
        // Obter as mensagens atualizadas para o chat específico
        const id_club = updatedChat.id_club;
        const updatedMessages = await Chat.find({ id_club }).sort({ timestamp: 'asc' });

        // Emitir evento para atualizar a lista de mensagens para o chat específico
        io.to(chatRoom).emit('updated message list', { id_club, messages: updatedMessages });
        
      } catch (err) {
        console.error('Error editing message:', err);
      }
    });
    
    // SOCKET DE DELEÇÃO DE MENSAGENS
    socket.on('delete message', async (infos) => {
      try {
        const { messageId, id_user } = infos;
        const chat = await Chat.findById(messageId);
        if (!chat) {
          console.error('Mensagem não encontrada');
          return;
        }

        // Verificar se o usuário que está tentando deletar a mensagem é o mesmo que a enviou
        if (parseInt(chat.id_user) !== parseInt(id_user)) {
          console.error('Usuário sem permissão de deletar a mensagem');
          return;
        }
        
        // Salvar a mensagem antiga antes de excluí-la
        const oldMessage = chat.message;

        // Atualizar a mensagem para "Esta mensagem foi excluída" e marcar como deletada
        chat.message = "Esta mensagem foi excluída";
        chat.deleted = true;
        chat.oldMessage = oldMessage; // Salvar a mensagem antiga em um campo separado, se necessário

        // Salvar as alterações no documento
        await chat.save();
            // Emitir evento para informar que deu certo a atualização da mensagem para o cliente
            socket.emit('message deleted response', "Mensagem excluída com sucesso");

        // Obter as mensagens atualizadas para o chat específico
        const id_club = chat.id_club;
        const updatedMessages = await Chat.find({ id_club }).sort({ timestamp: 'asc' });

        // Emitir evento para atualizar a lista de mensagens para o chat específico
        io.to(chatRoom).emit('updated message list', { id_club, messages: updatedMessages });
      } catch (err) {
        console.error('Error deleting message:', err);
      }
    });
  });
});
  
server.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});


Solution

  • Why you use io.connect(...) ? Can you put your frontend import? Is the code in a useeffect?

    From your code I can recommend you these steps:

    1. Try to use io from socket.io-client

      import {io} from "socket.io-client";
      
      //other code
      
      let newSocket = io('http://localhost:4444');
      //or let newSocket = io('195.XXX.XX4:4444');
      
      //other code
      
    2. You missed the socket.io Server:

      const { Server } = require("socket.io");
      //other import and code
      
      const io = new Server(server, {
          cors: {
              origin: ['http://localhost:3000'],
              methods: ['GET', 'POST'],
              allowedHeaders: ['Content-Type', 'Authorization'],
              credentials: true,
          },
          debug: true,
       });
      
    3. If you receive allow-origin error, add this to allowedHeaders of cors:

      allowedHeaders: ['Content-Type', 'Authorization','Access-Control-Allow-Origin', '*']
      
    4. Make sure you are not starting on port 3000.

      const port = process.env.PORT || 3000;
      

    Let me know if it works. If not, give me more info for my questions.