Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to monitor client disconnect / close connection? #41

Open
baagod opened this issue May 12, 2020 · 11 comments
Open

How to monitor client disconnect / close connection? #41

baagod opened this issue May 12, 2020 · 11 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@baagod
Copy link

baagod commented May 12, 2020

I want to do something when closing, or interrupting the client connection, such as cleaning up. I call conn.Close() on ws.OnConnect{} without triggering ws.OnDisconnect{}. what should I do?

package main

import (
    "fmt"
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/websocket"
    "github.com/kataras/neffos"
)

func main() {
    app := iris.Default()
    
    ws := neffos.New(websocket.DefaultGorillaUpgrader, neffos.Namespaces{
    	neffos.OnNativeMessage: neffos.Events{
    	    "login": func(ns *neffos.NSConn, msg neffos.Message) error {
    	        return nil
    	    },
    	},
    })
    
    ws.OnConnect = func(conn *neffos.Conn) error {
        allowConnect = true
        // some operations...
        if !allowConnect {
            conn.Close()
        }
    	return nil
    }
    
    ws.OnDisconnect = func(c *neffos.Conn) {
        // No shutdown signal is received and the method body is not triggered.
    	fmt.Println("OnDisconnect")
    }
    
    app.Get("/login", websocket.Handler(ws))
    app.Logger().Fatal(app.Listen(":8080"))
}
@kataras
Copy link
Owner

kataras commented May 18, 2020

@hjzCy You can't close the connection immediately from the ws.OnConnect event. If you want to close the connection from OnConnect you should return a NON-NIL ERROR. Also, there is a note on the code at:

neffos/server.go

Lines 174 to 179 in f143186

if s.OnDisconnect != nil {
// don't fire disconnect if was immediately closed on the `OnConnect` server event.
if !c.readiness.isReady() || (c.readiness.err != nil) {
continue
}
s.OnDisconnect(c)

We can change that if you want by an option(in order to not break existing behavior).

However, if you wait 1 second, it will be fired, although there is no logic on closing the connection without any checks when it's just connected (that's why we have the above check in the code too):

  ws.OnConnect = func(conn *neffos.Conn) error {
        time.Sleep(time.Second)
    	conn.Close()
    	return nil
    }

kataras added a commit that referenced this issue May 18, 2020
…nnect event if the server closed the connection from its OnConnect event: #41
@kataras
Copy link
Owner

kataras commented May 18, 2020

OK @hjzCy, a FireDisconnectAlways option was added.

$ go get github.com/kataras/neffos@v0.0.16
# or go.mod:
# require github.com/kataras/neffos v0.0.16
  ws := neffos.New([...])
  ws.FireDisconnectAlways = true // <---HERE

  ws.OnConnect = func(conn *neffos.Conn) error {
    	conn.Close()
    	return nil
}

ws.OnDisconnect = func(conn *neffos.Conn) {
    log.Printf("[%s] disconnected from the server.", c)
}

@kataras kataras added enhancement New feature or request good first issue Good for newcomers labels May 18, 2020
@baagod
Copy link
Author

baagod commented May 19, 2020

@kataras Thank you!very perfect!

@baagod
Copy link
Author

baagod commented May 19, 2020

@kataras
After setting FireDisconnectAlways = true, if the client suddenly disconnects, any data you want to get from the conn of the OnDisconnect{} method is invalid. And may cause the program to crash:

ws.OnDisconnect = apis.Logout

func Logout(conn *neffos.Conn) {
    ctx := websocket.GetContext(conn)
    token := strings.ReplaceAll(ctx.URLParam("token"), " ", "+")
    decode := aes.CBCDecrypt(token)

    // If `FireDisconnectAlways = false` then data can be obtained normally
    fmt.Println("token:", token)
    fmt.Println("decode:", decode)

    // If `FireDisconnectAlways = false`, it will execute normally.
    // Otherwise, the program will crash directly here ( Out of range )!!
    username := decode[:strings.Index(decode, ", ")]

    if client, ok := loginClients[username]; ok {
        if client.topStatus {
            log.Println("顶号断开连接,不删除用户数据。将顶号状态设置为 false。")
            client.topStatus = false
        } else {
            log.Println("异常、或正常断开连接,删除用户数据。")
            delete(loginClients, username)
        }
    }
}

@baagod
Copy link
Author

baagod commented May 19, 2020

The question now is that after the client disconnects, the data returned from conn is invalid. How can I still get the data from theOnDisconnect {}method after the client disconnects? E.g,Want to get the url parameter of this connection:

ctx := websocket.GetContext(conn)
fmt.Println("token:", ctx.URLParam("token")) // get failed, token is ""

@kataras
Copy link
Owner

kataras commented May 19, 2020

@hjzCy The connection is already closed and removed from the server when ws.OnDisconnect is fired (see

neffos/conn.go

Line 1039 in 15e3a17

c.server.disconnect <- c
). Why you don't use the neffos.OnNamespaceDisconnect event instead? It will be called on your conn.Close() too.

@baagod
Copy link
Author

baagod commented May 19, 2020

@kataras I cannot use neffos.OnNamespaceDisconnect because I need to use neffos.OnNativeMessage and my python client cannot connect to the namespace.

@baagod
Copy link
Author

baagod commented May 19, 2020

@kataras The two problems above are that I didn't manually call conn.Close (), but when the client disconnected, ws.OnDisconnect` received the signal automatically.

@baagod
Copy link
Author

baagod commented May 19, 2020

没有手动调用 conn.Close(),而是客户端由于某种原因断开了连接,此时 ws.OnDisconnect 接收到信号:

ws.OnDisconnect = apis.Logout

func Logout(conn *neffos.Conn) {
    ctx := websocket.GetContext(conn)
    // FireDisconnectAlways = false can get the result normally, otherwise "".
    fmt.Println("token:", ctx.URLParam("token"))
}

Cannot get url parameter data.

@baagod
Copy link
Author

baagod commented May 20, 2020

Well, I found that even if FireDisconnectAlways = true, sometimes when the client is suddenly disconnected, the conn data stored in the ws.OnDisconnect () method cannot be obtained.

A suggestion:
Is it possible to wait until the body of the ws.OnDisconnect() method is executed, and then disconnect from the conn, so that you can do some things by getting the data of conn when disconnecting.

@baagod
Copy link
Author

baagod commented May 21, 2020

Or add a signal: ws.onWillDisconnect() ?

LeeEirc pushed a commit to LeeEirc/neffos that referenced this issue Sep 8, 2020
…nnect event if the server closed the connection from its OnConnect event: kataras#41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants