Code Monkey home page Code Monkey logo

recws's Introduction

recws's People

Contributors

kevin96666 avatar loeffel-io avatar mariuspass avatar p4u avatar pivolan avatar sknr avatar theromis avatar uskudnik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

recws's Issues

KeepAlive implementation seems incorrect

     ticker            = time.NewTicker(rc.getKeepAliveTimeout())

...

if err := rc.writeControlPingMessage(); err != nil {
    log.Println(err)
}

<-ticker.C
if time.Since(keepAliveResponse.getLastResponse()) > rc.getKeepAliveTimeout() {
    rc.CloseAndReconnect()
    return
}

Shouldn't time.Since(keepAliveResponse.getLastResponse()) always be greater than keepAliveTimeout because it's waiting on the timer which is set to keepAliveTimeout???

I'm encountering the situation where the time since the last response is ever so slightly longer than keepAliveTimeout.

ignore TLS certificate error (self signed)

Hi,

Is there a way for ignoring SSL/TLS Certificats error ? My websocket dev server use TLS with a self signed certificate.

Note that after retrying after 2 seconds, recws enter into a loop for 2 seconds before closing ws, see #38

CloseAndReconnect() only Close but doesn't Reconnect

// CloseAndReconnect will try to reconnect.
func (rc *RecConn) CloseAndReconnect() {
	rc.Close()
	go rc.connect()
}

the Close() function send to the close chan

rc.close <- true

connect() will return if it receives from close chan

func (rc *RecConn) connect() {
	b := rc.getBackoff()
	rand.Seed(time.Now().UTC().UnixNano())

	for {
		select {
		case <-rc.close:
			return
....

in the end calling connect() right after Close() will not work.

Am I missing something here or it is a bug?

Infinite loop

In got an infinite loop once a day, after profiling the infinite loop is here at around line 375.

		for {
			if !rc.IsConnected() {
				continue
			}

It doesn't go away until I restart my application.

Cannot reconnect

version: v1.3.1
I am also using

&recws.RecConn{
		KeepAliveTimeout: 60 * time.Second,
	}

It kept reconnecting after the first connection reset, I also couldn't receive new messages afterwards.

image

not try to reconnect, 1.2.2

after socket is connected, restarted websocket server.

version 1.2.1

2020/12/30 14:33:38 read tcp [::1]:61619->[::1]:3000: read: connection reset by peer
2020/12/30 14:33:38 Dial: will try again in 2s seconds.
2020/12/30 14:33:40 dial tcp [::1]:3000: connect: connection refused
2020/12/30 14:33:40 Dial: will try again in 2.891027974s seconds.
2020/12/30 14:33:43 dial tcp [::1]:3000: connect: connection refused
2020/12/30 14:33:43 Dial: will try again in 2.909185715s seconds.
2020/12/30 14:33:46 dial tcp [::1]:3000: connect: connection refused
2020/12/30 14:33:46 Dial: will try again in 2.856300582s seconds.
2020/12/30 14:33:48 dial tcp [::1]:3000: connect: connection refused
2020/12/30 14:33:48 Dial: will try again in 7.599538362s seconds.

retry and connecting is succeed, but

version 1.2.2

not retry and just fail error message

disconnected loop while waiting for redial only after first retry

Code (from example, but use ws rather than wss)

The server is a raw ws nodejs app, working perfectly with a golang client using gorilla websocket.

package main

import (
	"context"
	"log"
	"time"

	"github.com/recws-org/recws"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	ws := recws.RecConn{
		KeepAliveTimeout: 10 * time.Second,
	}
	ws.Dial("ws://192.168.56.101", nil)

	go func() {
		time.Sleep(2 * time.Second)
		cancel()
	}()

	for {
		select {
		case <-ctx.Done():
			go ws.Close()
			log.Printf("Websocket closed %s", ws.GetURL())
			return
		default:
			if !ws.IsConnected() {
				log.Printf("Websocket disconnected %s", ws.GetURL())
				continue
			}

			if err := ws.WriteMessage(1, []byte("Incoming")); err != nil {
				log.Printf("Error: WriteMessage %s", ws.GetURL())
				return
			}

			_, message, err := ws.ReadMessage()
			if err != nil {
				log.Printf("Error: ReadMessage %s", ws.GetURL())
				return
			}

			log.Printf("Success: %s", message)
		}
	}
}

14:25:30 => 14:25:32 = OK, waiting
14:25:32 => 14:25:34 = disconnected loop ?
14:25:34 = closing

2021/03/17 14:25:30 websocket: bad handshake
2021/03/17 14:25:30 Dial: will try again in 2s seconds.
2021/03/17 14:25:32 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:32 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:32 Websocket disconnected ws://192.168.56.101
.....
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket disconnected ws://192.168.56.101
2021/03/17 14:25:34 Websocket closed ws://192.168.56.101

Unhandled error causing panic

Hi,

I encountered the following error in my application:

panic: runtime error: invalid memory address or nil pointer dereference[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7d96d0]goroutine 59856 [running]:github.com/gorilla/websocket.(*Conn).SetPongHandler(0x0, 0xc003712960) /go/pkg/mod/github.com/gorilla/[email protected]/conn.go:1160 +0x20github.com/recws-org/recws.(*RecConn).keepAlive(0x1399a00) /go/pkg/mod/github.com/recws-org/[email protected]/recws.go:365 +0xc5github.com/recws-org/recws.(*RecConn).connect(0x1399a00) /go/pkg/mod/github.com/recws-org/[email protected]/recws.go:422 +0x3cacreated by github.com/recws-org/recws.(*RecConn).CloseAndReconnect /go/pkg/mod/github.com/recws-org/[email protected]/recws.go:64 +0x4d

Looks to happen because the error on this line is not being handled, but I might be wrong:

recws/recws.go

Line 365 in 37f9e46

rc.Conn.SetPongHandler(func(msg string) error {

Any ideas how to go about this?

Thank you.

[proposal] Method to wait for re-connect after connection loss

Currently I do it this way, but find it rather unclean:

for {
  if !ws.IsConnected() {
    time.Sleep(time.Second * 2)
    continue
  }

  // Do stuff with connection
}

One idea I have is to export the getBackoff() method to wait for the correct time until trying to read a new message. Another idea is to have a method WaitConnection() / EnsureConnection(), which blocks until the connection is reestablished. I am happy to create a PR for either of the proposals.

After close 1006 reconnection does not happen

After abnormal closure, automatic reconnection does not happen:

2023/07/24 19:26:15 Connected to server:ws://localhost:8081/connect
2023/07/24 19:26:15 websocket read error: websocket: close 1006 (abnormal closure): unexpected EOF
2023/07/24 19:26:15 websocket read error: websocket: not connected
2023/07/24 19:26:15 websocket read error: websocket: not connected
2023/07/24 19:26:15 websocket read error: websocket: not connected
...
	for _, conn := range connections {
		go func(conn *recws.RecConn) {
			for {
			start:
				_, msg, err := conn.ReadMessage()
				if err != nil {
					log.Println("websocket read error:", err)
					continue
				}
			...
			}
		}(conn)
	...

Basic example: After reconnect messages aren't being received

I adapted the basic example to just listen for incoming messages, if the websocket server goes down, recws correctly retries to connect but then the messages are no longer received.

Expected behaviour, the messages continue to be received OK. You can see the messages received before disconnect but not afterwards.

image

Adapted example

package main

import (
	"context"
	"github.com/recws-org/recws"
	"log"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	ws := recws.RecConn{
		KeepAliveTimeout: 10 * time.Second,
	}
	ws.Dial("wss://echo.websocket.org", nil)

	go func() {
		time.Sleep(2 * time.Second)
		cancel()
	}()

	for {
		select {
		default:
			if !ws.IsConnected() {
				log.Printf("Websocket disconnected %s", ws.GetURL())
				continue
			}

			_, message, err := ws.ReadMessage()
			if err != nil {
				log.Printf("Error: ReadMessage %s", ws.GetURL())
				return
			}

			log.Printf("Success: %s", message)
		}
	}
}

v1.3.0 module broken due to duplicate makefile

When trying to get the new v1.3.0:

go: github.com/recws-org/[email protected]: verifying go.mod: github.com/recws-org/[email protected]/go.mod: reading https://sum.golang.org/lookup/github.com/recws-org/[email protected]: 410 Gone
        server response: not found: create zip: makefile: case-insensitive file name collision: "Makefile" and "makefile"

I believe this is due to upstream issue : golang/go#33778

Can you please collapse the 2 Makefiles into 1 and release a v1.3.1?

Thanks!

Better approach

Was playing around with this lib trying to have a fault tolerant ws connection. Tried patches from different prs and forks, still there was a present problem with race - multiple reconnects occurring from time to time. Also making a custom heartbeat is a headache.

And realised, why not just wrap the ws listener in infinite cycle?

	for {
		select {
		case <-ctx.Done():
			return
		default:
			err := InitAndListenWs()
			if err != nil {
				....
			}
		}
	}

No concurrency problems and easy to implement.

High CPU usage in example when disconnected

Using the basic example, the code below will flood the console and cause 100% CPU usage on a single core;

if !ws.IsConnected() {
	log.Printf("Websocket disconnected %s", ws.GetURL())
	continue
}

It's not the most elegant solution, but an easy fix is to do something like this:

if !rm.conn.IsConnected() {
	<-time.After(rm.conn.RecIntvlMin)
	continue
}

Is there a better way to do this? It doesn't look like there's a connected channel to block on.

Update Release/Tag

go get fetches the 1.0.0 tag, which includes the wrong import path. Thus a new tagged release is needed to fix go get.

Thank you!

Thank you so much for this package! ๐ŸŽ‰ ๐Ÿ‘

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.