HomeiOS DevelopmentSocket.io consumer for Swift can't connect with node.js server

Socket.io consumer for Swift can’t connect with node.js server


I’m making an attempt to make use of the newest model of Swift package deal socket.io-client-swift to hook up with my socket.io server inbuilt Node.js, however no connection ever appears to be made, as a result of nothing is logged within the console indicating {that a} connection was efficiently made – no polling, no established handshake.

These are the logs that happen within the app indicating {that a} connection can’t be established:

LOG SocketIOClient{/}: Including handler for occasion: join
LOG SocketIOClient{/}: Including handler for occasion: disconnect
LOG SocketIOClient{/}: Including handler for occasion: error
LOG SocketIOClient{/}: Dealing with occasion: statusChange with information: [connecting, 2]
LOG SocketIOClient{/}: Becoming a member of namespace /
LOG SocketManager: Tried connecting socket when engine is not open. Connecting
LOG SocketManager: Including engine
LOG SocketEngine: Beginning engine. Server: https://ws.my-socket-server.com
LOG SocketEngine: Handshaking
LOG SocketManager: Supervisor is being launched
LOG SocketIOClient{/}: Including handler for occasion: join
LOG SocketIOClient{/}: Including handler for occasion: disconnect
LOG SocketIOClient{/}: Including handler for occasion: error
LOG SocketIOClient{/}: Dealing with occasion: statusChange with information: [connecting, 2]
LOG SocketIOClient{/}: Becoming a member of namespace /
LOG SocketManager: Tried connecting socket when engine is not open. Connecting
LOG SocketManager: Tried connecting an already lively socket

As you possibly can see, it says “Tried connecting socket when engine is not open” & releases the Supervisor very early.

Right here is my singleton WebSocketManager I’m creating to share the socket with all of my views:

import Basis
import SocketIO

class WebSocketManager: NSObject, ObservableObject, URLSessionWebSocketDelegate {
    static let shared = WebSocketManager()

    @Revealed var drawingSocket: SocketIOClient?
    personal var drawingSocketManager: SocketManager?
    personal let drawingSocketURL = URL(string: "https://ws.my-socket-server.com")!

    override personal init() {
        tremendous.init()
        setupDrawingSocket()
    }

    personal func setupDrawingSocket() {
        drawingSocketManager = SocketManager(socketURL: drawingSocketURL, config: [.log(true), .reconnectAttempts(5), .reconnectWaitMax(5), .forceWebsockets(true)])
        drawingSocket = drawingSocketManager?.defaultSocket

        drawingSocket?.on(clientEvent: .join) { _, _ in
            print("Drawing socket related")
        }
        drawingSocket?.on(clientEvent: .disconnect) { information, _ in
            print("Drawing socket disconnected: (information)")
        }
        drawingSocket?.on(clientEvent: .error) { information, _ in
            print("Drawing socket error: (information)")
        }
        if drawingSocket?.standing != .related {
            drawingSocket?.join()
        }
    }

    func sendDrawingMessage(_ motion: String, information: Any) {
        guard let drawingSocket = drawingSocket else {
            print("Drawing socket isn't obtainable")
            return
        }

        // Examine if the socket is related earlier than sending a message
        if drawingSocket.standing == .related {
            drawingSocket.emit(motion, information as! SocketData)
        } else {
            print("Drawing socket isn't related. Can't ship message.")
        }
    }

    var isDrawingSocketConnected: Bool {
        return drawingSocket?.standing == .related
    }
}

Right here is the entrypoint to all of my views:

import SwiftUI

@fundamental
struct my_iosApp: App {
    var physique: some Scene {
        WindowGroup {
            Residence()
                .environmentObject(WebSocketManager.shared)
                .environmentObject(GlobalStateManager.shared)
        }
    }
}

and eventually, right here is the place I’m utilizing the socket to emit a message to the server:

import SocketIO
import SwiftUI

struct GameCodeDisplay: View {
    @EnvironmentObject var globalStateManager: GlobalStateManager
    @EnvironmentObject var webSocketManager: WebSocketManager
    let gameCode: String
    var onCancel: () -> Void
    personal var drawingSocket: SocketIOClient

    init(gameCode: String, onCancel: @escaping () -> Void) {
        self.gameCode = gameCode
        self.onCancel = onCancel

        let supervisor = SocketManager(socketURL: URL(string: "https://ws.my-socket-server.com")!, config: [.log(true), .reconnectAttempts(5), .reconnectWaitMax(5), .forceWebsockets(true)])
        self.drawingSocket = supervisor.defaultSocket
    }

    var physique: some View {
        ZStack {
            Coloration(crimson: 115.0 / 255.0, inexperienced: 5.0 / 255.0, blue: 60.0 / 255.0)
                .edgesIgnoringSafeArea(.all)

            VStack {
                Spacer() // Pushes content material to the middle

                Textual content("Your recreation code is:")
                    .font(.title)
                    .fontWeight(.daring)
                    .foregroundColor(.white)

                Textual content(gameCode)
                    .font(.largeTitle)
                    .fontWeight(.daring)
                    .foregroundColor(.white)
                    .padding(.backside)

                ScrollView {
                    VStack {
                        ForEach(globalStateManager.gamers, id: .self) { participant in
                            Textual content(participant)
                                .body(maxWidth: .infinity)
                                .multilineTextAlignment(.heart)
                                .foregroundColor(.white)
                        }
                    }
                }
                .body(maxHeight: 200) // Modify as wanted

                if globalStateManager.gamers.depend >= 5 {
                    Button("Begin!") {
                        startGame(drawingSocket: drawingSocket, gameCode: gameCode)
                    }
                    .disabled(globalStateManager.gamers.depend < 5)
                    .padding()
                    .foregroundColor(.inexperienced)
                }

                Button("Cancel") {
                    onCancel()
                    leaveGame(webSocketManager: webSocketManager, globalStateManager: globalStateManager)
                }
                .padding()
                .foregroundColor(.yellow)

                Spacer() // Permits the button to be on the backside
            }
            .body(maxWidth: .infinity, maxHeight: .infinity)
            .padding() // Add padding across the complete VStack
        }.onAppear {
            setupDrawingSocketEvents()
        }
    }

    personal func setupDrawingSocketEvents() {
        guard let drawingSocket = webSocketManager.drawingSocket else {
            print("Drawing socket not obtainable")
            return
        }

        drawingSocket.on(clientEvent: .join) { _, _ in
            print("Drawing socket related")
            // Further code for when the socket connects
        }

        drawingSocket.on(clientEvent: .disconnect) { information, _ in
            print("Drawing socket disconnected: (information)")
            // Further code for when the socket disconnects
        }

        drawingSocket.on(clientEvent: .error) { information, _ in
            print("Drawing socket error: (information)")
            // Further error dealing with
        }

        // Hook up with the socket if not related
        if !webSocketManager.isDrawingSocketConnected {
            drawingSocket.join()
        }
    }

    personal func startGame(drawingSocket: SocketIOClient, gameCode: String) {
        print("GameCodeDisplay: Beginning recreation with gameCode - (gameCode)")
        webSocketManager.sendDrawingMessage("joinGame", information: gameCode)
        webSocketManager.sendDrawingMessage("startGame", information: gameCode)
    }

    personal func leaveGame(webSocketManager: WebSocketManager, globalStateManager: GlobalStateManager) {
        print("GameCodeDisplay: Leaving recreation with gameCode - (gameCode)")
        webSocketManager.sendLeaveGameMessage(gameCode: gameCode, username: globalStateManager.username)
        webSocketManager.disconnect()
        globalStateManager.gamers.removeAll()
        globalStateManager.setUsername(usernameToSet: "")
    }
}

Right here is Node.js server that the socket is operating on. I’m utilizing model socket.io: “^4.7.2”:

const categorical = require("categorical");
const { Server } = require("socket.io");
const cors = require("cors");
const http = require("http");

const allowedOrigins = [
  "https://website-1.com",
  "https://website-2.com",
  "http://localhost:3000",
];
const app = categorical();
app.use(
  cors({
    origin: perform (origin, callback) {
      console.log("origin: ", origin);
      if (!origin) return callback(null, true); // Enable requests with no origin (like cell apps or curl requests)
      if (allowedOrigins.indexOf(origin) === -1) {
        const msg =
          "The CORS coverage for this web site doesn't permit entry from the desired Origin.";
        return callback(new Error(msg), false);
      }
      return callback(null, true);
    },
  })
);
app.get("/health-check", (req, res) => res.standing(200).ship("OK"));
const server = http.createServer(app);
const io = new Server(server, {
  transports: ["websocket"],
  cors: {
    origin: perform (origin, callback) {
      if (allowedOrigins.indexOf(origin) !== -1) {
        callback(null, true);
      } else {
        callback(new Error("Not allowed by CORS"));
      }
    },
    strategies: ["GET", "POST"],
  },
});

const connectedSockets = new Set();

io.on("connection", (socket) => {
  connectedSockets.add(socket);

  socket.on("joinGame", (gameCode, callback) => {
    socket.be part of(gameCode);
    console.log(`Socket with ID ${socket.id} joined room: ${gameCode}`);
    if (typeof callback === "perform") {
      callback(`Joined room: ${gameCode}`);
    }
  });
  socket.on("startGame", (gameCode) => {
    console.log("Emitting gameStarted to room:", gameCode);
    io.to(gameCode).emit("gameStarted");
  });
});

server.hear(3001, (err) => {
  connectedSockets.forEach((socket) => {
    socket.disconnect(true);
  });
  connectedSockets.clear();
  if (err) throw err;
  console.log("> Prepared on http://localhost:3001");
});

I’ve tried a wide range of alternative ways of making that singleton I discussed of the WebSocketManager to no avail. At this level, I’m open to another Swift package deal options to hook up with my socket.io server from my SwiftUI iOS app.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments