将 Socket.io 与 Next.js 结合使用

Lev*_*tna 6 sockets node.js socket.io next.js socket.io-client

背景

我正在尝试使用 Next.js 建立并连接套接字。我正在遵循标准指南,该指南使用 API 调用来测试套接字服务器是否已在运行,如果没有则创建一个。

我有一个 API 脚本,pages/api/socket/io如下所示:

import { Server } from "socket.io";

export default function SocketHandler(req, res) {

    if (res.socket.server.io) {
        console.log("Already set up");
        res.end();
        return;
    }

    const io = new Server(res.socket.server);

    // Event handler for client connections
    io.on('connection', (socket) => {
        const clientId = socket.id;
        console.log('A client connected');
        console.log(`A client connected. ID: ${clientId}`);
        io.emit('client-new', clientId);

        // Event handler for receiving messages from the client
        socket.on('message', (data) => {
            console.log('Received message:', data);
        });

        // Event handler for client disconnections
        socket.on('disconnect', () => {
            console.log('A client disconnected.');
        });
    });

    res.socket.server.io = io;
    res.end();
}
Run Code Online (Sandbox Code Playgroud)

我在pages/chat.js该 ping下有一个页面/api/socket/io,以确保套接字服务器正在运行,然后尝试连接到它。

import React, { useEffect, useState } from "react";
import io from "socket.io-client";

let socket;

const Page = () => {
    const [message, setMessage] = useState("");
    const [username, setUsername] = useState("");

    useEffect(() => {
        socketInitializer();

        return () => {
            socket.disconnect();
        };
    }, []);

    async function socketInitializer() {

        // ping the server to setup a socket if not already running
        await fetch("/api/socket/io");

        // Setup the Socket 
        socket = io({ path: "/api/socket/ping" });

        // Standard socket management
        socket.on('connect', () => {
            console.log('Connected to the server');
        });

        socket.on('disconnect', () => {
            console.log('Disconnected from the server');
        });

        socket.on('connect_error', (error) => {
            console.log('Connection error:', error);
        });

        socket.on('reconnect', (attemptNumber) => {
            console.log('Reconnected to the server. Attempt:', attemptNumber);
        });

        socket.on('reconnect_error', (error) => {
            console.log('Reconnection error:', error);
        });

        socket.on('reconnect_failed', () => {
            console.log('Failed to reconnect to the server');
        });

        // Manage socket message events
        socket.on('client-new', (message) => {
            console.log("new client", message);
        });

        socket.on('message', (message) => {
            console.log("Message", message);
        });

        socket.on('client-count', (count) => {
            console.log("clientCount", count)
        });

    }

    function handleSubmit(e) {
        e.preventDefault();

        socket.emit("message", {
            username,
            message
        });

        setMessage("");
    }

    return (
        <div>
            <h1>Chat app</h1>
            <h1>Enter a username</h1>

            <input value={username} onChange={(e) => setUsername(e.target.value)} />

            <div>
                <form onSubmit={handleSubmit}>
                    <input
                        name="message"
                        placeholder="enter your message"
                        value={message}
                        onChange={(e) => setMessage(e.target.value)}
                        autoComplete={"off"}
                    />
                </form>
            </div>
        </div>
    );
};

export default Page;
Run Code Online (Sandbox Code Playgroud)

/api/socket/ping是一个简单的脚本,除了返回正常状态之外没有做太多事情。我假设它应该检查服务器是否正在运行并保存任何逻辑来检查客户端将来是否仍然有效,但此时它不应该阻止客户端连接。

它看起来像这样:

export default async function handler(req, res) {
    return res.status(200).send("OK");
}

Run Code Online (Sandbox Code Playgroud)

问题

我遇到的问题是套接字服务器似乎正在设置。但是,我无法让客户端连接。

我收到一条错误消息,表明我可能需要在客户端设置过程中提供一些额外的配置选项socket = io({ path: "/api/socket/ping" });,但我不确定从哪里开始。

我在本地主机端口 3000 上运行服务器。这是我收到的错误:

Connection error: Error: server error
    at Socket.onPacket (socket.js:318:1)
    at Emitter.emit (index.mjs:136:1)
    at Polling.onPacket (transport.js:97:1)
    at callback (polling.js:115:1)
    at Array.forEach (<anonymous>)
    at Polling.onData (polling.js:118:22)
    at Emitter.emit (index.mjs:136:1)
    at Request.onLoad (polling.js:361:1)
    at xhr.onreadystatechange (polling.js:297:1)
Run Code Online (Sandbox Code Playgroud)

要求

请解释客户端无法连接的原因并提出解决问题的建议。

Lou*_*uis 3

import { Server } from "socket.io";
import cors from "cors";
import nextConnect from "next-connect";

const handler = nextConnect();

// Enable CORS
handler.use(cors());

handler.all((req, res) => {
  if (res.socket.server.io) {
    console.log("Already set up");
    res.end();
    return;
  }

  const io = new Server(res.socket.server);

  // Event handler for client connections
  io.on("connection", (socket) => {
    const clientId = socket.id;
    console.log("A client connected");
    console.log(`A client connected. ID: ${clientId}`);
    io.emit("client-new", clientId);

    // Event handler for receiving messages from the client
    socket.on("message", (data) => {
      console.log("Received message:", data);
    });

    // Event handler for client disconnections
    socket.on("disconnect", () => {
      console.log("A client disconnected.");
    });
  });

  res.socket.server.io = io;
  res.end();
});

export default handler;
Run Code Online (Sandbox Code Playgroud)

  • 如何使用新的 Nextjs 14 api 路由来实现这一点。 (2认同)