mrniko / netty-socketio

Socket.IO server implemented on Java. Realtime java framework
Apache License 2.0
6.82k stars 1.65k forks source link

Server Response: Invalid namespace #903

Closed luoxiaofeng1029 closed 1 year ago

luoxiaofeng1029 commented 1 year ago

issue details in python-socketio

The author of python-socketio told me that it is a server-side issue, but I can't seem to find the problem. Please help me by combining the link description above and the server-side code example below. Thank you.

`@Slf4j @Service public class SocketIOService {

private final SocketIOServer server;
private final ApplicationEventPublisher eventPublisher;

@Autowired
public SocketIOService(SocketIOServer server, ApplicationEventPublisher eventPublisher) {
    this.server = server;
    this.eventPublisher = eventPublisher;
}

@PostConstruct
public void start() {

    // 为新命名空间添加事件监听器
    server.addConnectListener(this::onConnect);
    server.addDisconnectListener(this::onDisconnect);
    server.addPongListener(this::onPong);
    server.addEventListener("message", String.class, this::onTextMessage);
    server.addEventListener("binary", byte[].class, this::onBinaryMessage);

    server.start();
}

private void onConnect(SocketIOClient client) {
    String token = client.getHandshakeData().getSingleUrlParam("token");
    LoginUser loginUser;
    try {
        loginUser = LoginHelper.getLoginUser(token);
        loginUser.setToken(token);
    } catch (NullPointerException | NotLoginException e) {
        log.error("ws:登录认证失败,握手失败!", e);
        client.disconnect();
        return;
    }
    client.set(LOGIN_USER_KEY, loginUser);
    SocketIoClientHolder.addClient(loginUser.getUserId(), client);
    log.info("[ws-connected] userId: {}", loginUser.getUserId());
    SocketIOUtils.sendMessage(client, "from server: connect-success");
}

private void onDisconnect(SocketIOClient client) {
    LoginUser loginUser = client.get(LOGIN_USER_KEY);
    SocketIoClientHolder.removeClient(loginUser.getUserId());
    log.info("[ws-disconnect] userId: {},", loginUser.getUserId());
}

private void onPong(SocketIOClient client) {
    log.info("ws-pong, userId:" + client.get(LOGIN_USER_KEY));
}

private void onTextMessage(SocketIOClient client, String message, AckRequest ackSender) {
    log.info("ws-text, message:" + message);
    LoginUser loginUser = client.get(LOGIN_USER_KEY);
    eventPublisher.publishEvent(new WebSocketMessageEvent(this, loginUser, message));
}

private void onBinaryMessage(SocketIOClient client, byte[] message, AckRequest ackSender) {
    LoginUser loginUser = (LoginUser) client.get(LOGIN_USER_KEY);
    log.info("ws-binary, userId:" + loginUser.getUserId());

}

@PreDestroy
public void stop() {
    server.stop();
}

} @Slf4j @Configuration public class SocketIOConfig {

@Value("${socketIo.host}")
private String host;

@Value("${socketIo.port}")
private Integer port;

@Value("${socketIo.bossCount}")
private int bossCount;

@Value("${socketIo.workCount}")
private int workCount;

@Value("${socketIo.allowCustomRequests}")
private boolean allowCustomRequests;

@Value("${socketIo.pingTimeout}")
private int pingTimeout;

@Value("${socketIo.pingInterval}")
private int pingInterval;

@Bean
public SocketIOServer socketIOServer() {
    SocketConfig socketConfig = new SocketConfig();
    socketConfig.setTcpNoDelay(true);
    socketConfig.setSoLinger(0);
    com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
    config.setSocketConfig(socketConfig);
    config.setHostname(host);
    config.setPort(port);
    config.setBossThreads(bossCount);
    config.setWorkerThreads(workCount);
    config.setAllowCustomRequests(allowCustomRequests);
    config.setPingTimeout(pingTimeout);
    config.setPingInterval(pingInterval);
    config.setOrigin(null);
    return new SocketIOServer(config);
}

} --- # socket.io socketIo: host: 192.168.10.2 port: 8098 bossCount: 1 workCount: 100 allowCustomRequests: true pingTimeout: 20000 pingInterval: 30000`

luoxiaofeng1029 commented 1 year ago

@mrniko

luoxiaofeng1029 commented 1 year ago

@mrniko Could you spare a few minutes to help me analyze this problem? It has been bothering me for a long time. Thank you very much.

luoxiaofeng1029 commented 1 year ago

@mrniko

lyjnew commented 1 year ago

V4 have some error 我修补它 https://github.com/lyjnew/netty-socketio-patch

luoxiaofeng1029 commented 1 year ago

V4 have some error 我修补它 https://github.com/lyjnew/netty-socketio-patch

我如何把官方的版本换成你的版本呢?

lyjnew commented 1 year ago

image

lyjnew commented 1 year ago

java8 https://github.com/lyjnew/netty-socketio-patch/files/11896219/netty-socketio-2.0.2-pach.jar.zip repalce netty-socketio-2.0.2.jar

luoxiaofeng1029 commented 1 year ago

java8 https://github.com/lyjnew/netty-socketio-patch/files/11896219/netty-socketio-2.0.2-pach.jar.zip repalce netty-socketio-2.0.2.jar

Thank you for your response. It is unfortunate that this author is no longer maintaining or addressing the issues we raised.

luoxiaofeng1029 commented 1 year ago

java8 https://github.com/lyjnew/netty-socketio-patch/files/11896219/netty-socketio-2.0.2-pach.jar.zip repalce netty-socketio-2.0.2.jar

I just replaced your patch, but I am still getting the error for my issue. I hope you can carefully review my description of the problem and the reference to another issue above. It seems like the current patch did not solve my problem.

lyjnew commented 1 year ago

@luoxiaofeng1029 give me you python-socketio connect code ,i test you code

luoxiaofeng1029 commented 1 year ago

@luoxiaofeng1029 给我你的python-socketio连接代码,我测试你的代码

`import requests import socketio import cv2 import base64 sio = socketio.Client(logger=True, engineio_logger=True)

@sio.event def connect(): print('connected to server')

@sio.event def disconnect(): print('disconnected from server')

if name == 'main': server_ip = '192.168.10.2' server_port = '8098' res = requests.post(f"http://{server_ip}:8088/benchLogin", json={"username": "admin","password": "123456"}).json() print(res) token = res['data']['token'] sio.connect(f"ws://{server_ip}:{server_port}?token={token}", transports=['websocket']) sio.wait() `

image

lyjnew commented 1 year ago

ok i find the error not the [netty-socketio] error the python-socketio client error ,i change client code ,all rgiht image

lyjnew commented 1 year ago

error in python-socketio-main\src\socketio\client.py line 683 change this image

lyjnew commented 1 year ago

if use public Python-socketio i test use this code sio.connect(f"ws://localhost:8080", transports=['websocket'])

client send nsp={} packet too

luoxiaofeng1029 commented 1 year ago

python-socketio-main\src\socketio\client.py 第 683 行中的错误更改此 图像

After making the modifications as per your suggestion, the error is indeed resolved. However, is it really a mistake that the author of python-socketio added "or {}" at the end? I don't have extensive coding knowledge to understand the reason behind adding "or {}", so should I raise an issue to provide feedback to the developer? But I have previously approached this developer, and he mentioned that the server returned an incorrect message body.

luoxiaofeng1029 commented 1 year ago

ok i find the error not the [netty-socketio] error the python-socketio client error ,i change client code ,all rgiht image

Additionally, I noticed that when python-socketio successfully connects, it triggers the "connect" event in netty-socketio twice.

` @PostConstruct public void start() {

    // 为新命名空间添加事件监听器
    server.addConnectListener(this::onConnect);
    server.addDisconnectListener(this::onDisconnect);
    server.addPongListener(this::onPong);
    server.addPingListener(this::onPing);
    server.addEventListener("message", String.class, this::onTextMessage);
    server.addEventListener("videoStream", String.class, this::onVideoStreamReceived);

    server.start();
}

private void onConnect(SocketIOClient client) {
    LoginUser loginUser = JSONUtil.toBean(client.getHandshakeData().getHttpHeaders().get(LOGIN_USER_KEY), LoginUser.class);
    client.set(LOGIN_USER_KEY, loginUser);
    SocketIoClientHolder.addClient(loginUser.getUserId(), client);
    log.info("[ws-connected] userId: {}", loginUser.getUserId());
    SocketIOUtils.sendMessage(client, "from server: connect-success");
}`

@lyjnew

lyjnew commented 1 year ago

"This is also a standard. Returning this in JavaScript results in an empty set, which is normal if received by a Node service. Socket.io's Node version also follows this approach. However, Java may encounter issues with this. If you want to use this standard, modify the code at this location." netty-socketio\src\main\java\com\corundumstudio\socketio\protocol\Packet.java line 112 to this image

luoxiaofeng1029 commented 1 year ago

“这也是一个标准。在 JavaScript 中返回这个会导致空值,如果由 Node 服务接收,这是正常的。Socket.io 的 Node 版本也遵循这种方法。但是,Java 可能会遇到问题。如果你想使用这个标准,修改这个位置的代码。” netty-socketio\src\main\java\com\corundumstudio\socketio\protocol\Packet.java 第 112 行 到此 图像

我感觉还是按照你之前的方法,修改客户端的代码比较方便,哈哈,谢谢

lyjnew commented 1 year ago

nice

luoxiaofeng1029 commented 1 year ago

nice

are you chinese? You are truly very enthusiastic.

lyjnew commented 1 year ago

new relase this patch https://github.com/lyjnew/netty-socketio-patch/files/11904921/netty-socketio-2.0.2-patch.jar.zip

lyjnew commented 1 year ago

@luoxiaofeng1029

ok i find the error not the [netty-socketio] error the python-socketio client error ,i change client code ,all rgiht image

Additionally, I noticed that when python-socketio successfully connects, it triggers the "connect" event in netty-socketio twice.

@lyjnew

======== **Socket.io protocol https://socket.io/docs/v4/socket-io-protocol/#connection-to-a-namespace

1. client send step 1: connect open send 0 --> server return: 0{"sid":"a4b107b8-daad-4668-806a-3c60aa2ea060","upgrades":[],"pingInterval":25000,"pingTimeout":60000}

2. client send step 2: connect open send 0+"namespace" --> server return: "namespace"+ {"sid":"f0aa3013-3475-468e-933f-6e4d07bfd7c3"}

image

your namespace value is empty value ,so The connection requests your received. look like twice same connect ,

3. If there is a namespace, it would be completely different. The server can also receive two different connection requests, the first with nsp="", and the second with nsp=chat

image

======================================================= i suggest not using the default namespace because V5 will change it https://github.com/socketio/socket.io-protocol#difference-between-v5-and-v4 image

luoxiaofeng1029 commented 1 year ago

@luoxiaofeng1029

好吧,我发现错误不是 [netty-socketio] 错误,而是 python-socketio 客户端错误,我更改了客户端代码,所有正确的代码图像

另外,我注意到当 python-socketio 成功连接时,它会触发 netty-socketio 中的“connect”事件两次。

@lyjnew

======== **Socket.io协议https://socket.io/docs/v4/socket-io-protocol/#connection-to-a-namespace

1. 客户端发送步骤1:连接打开发送0 --> 服务器返回:0{"sid":"a4b107b8-daad-4668-806a-3c60aa2ea060","upgrades":[],"pingInterval":25000," ping超时“:60000}

2.客户端发送第2步:connect open send 0+"namespace" --> 服务器返回:"namespace"+ {"sid":"f0aa3013-3475-468e-933f-6e4d07bfd7c3"}

图像

您的命名空间设为空值,因此收到的连接请求。看起来像两次相同的连接,

3.如果有命名空间,那就不一样了。服务器还可以完全接收两个不同的连接请求,第一个是 nsp="",第二个是 nsp=chat

图像

=================================================== = ===== 我建议不要使用默认命名空间,因为 V5 会更改它 https://github.com/socketio/socket.io-protocol#difference- Between-v5-and-v4 图像

All of my questions have been resolved, thank you for patiently helping me clear all my confusions. I don't know how to express my gratitude.

mrniko commented 1 year ago

fixed