Git Product home page Git Product logo

websocket's Introduction

websocket

GoDoc

Packages websocket and websocketjs provide high- and low-level bindings for the browser's WebSocket API (respectively).

The high-level bindings offer a Dial function that returns a regular net.Conn. It can be used similarly to net package.

conn, err := websocket.Dial("ws://localhost/socket") // Blocks until connection is established.
if err != nil {
	// handle error
}

buf := make([]byte, 1024)
n, err = conn.Read(buf) // Blocks until a WebSocket frame is received.
doSomethingWithData(buf[:n])
if err != nil {
	// handle error
}

_, err = conn.Write([]byte("Hello!"))
// ...

err = conn.Close()
// ...

The low-level bindings work with typical JavaScript idioms, such as adding event listeners with callbacks.

ws, err := websocketjs.New("ws://localhost/socket") // Does not block.
if err != nil {
	// handle error
}

onOpen := func(ev *js.Object) {
	err := ws.Send([]byte("Hello!")) // Send a binary frame.
	// ...
	err := ws.Send("Hello!") // Send a text frame.
	// ...
}

ws.AddEventListener("open", false, onOpen)
ws.AddEventListener("message", false, onMessage)
ws.AddEventListener("close", false, onClose)
ws.AddEventListener("error", false, onError)

err = ws.Close()
// ...

Alternatives

websocket's People

Contributors

bign8 avatar dmitshur avatar johanbrandhorst avatar nhooyr 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websocket's Issues

Should Dial return a net.Conn?

cc @shurcooL

Pending release of gopherjs/gopherjs#89,

Should Dial return a net.Conn?

I believe the idiomatic Go way would be to follow the guidelines of net.TCPConn (& co.) in having a WebSocket(Conn) that is exported and fulfills net.Conn, but have Dial return a net.Conn and allow type-assertion if the consumer needs the low-level functionality of the WebSocket(Conn).

This refactor would, more than likely, break API compatibility.

Thoughts?

Import of net package causes os.Open syscall in net.maxListenerBacklog

I just ran into an issue using the latest versions of github.com/gopherjs/gopherjs and github.com/gopherjs/websocket wihch seems to be caused by websocket pulling in the stdlib net package. net has a global variable var listenerBacklog = maxListenerBacklog() in net/net.go which gets initialized during package initialization. In the browser at runtime this initialization causes a call to os.Open("/proc/sys/net/core/somaxconn") which triggers the following error on the JS console:

warning: system calls not available, see https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md

The solution that worked for me was to add the following stub to github.com/gopherjs/gopherjs/compiler/natives/net/net.go:

func maxListenerBacklog() int {
    return 0x80
}

where 0x80 is the value of syscall.SOMAXCONN for Linux. I'm using Go 1.4.1 on linux_amd64.

sporadic runtime error: send on closed channel

I am sporadically seeing this error at:
https://github.com/gopherjs/websocket/blob/master/conn.go#L130
Presumably it could also happen at:
https://github.com/gopherjs/websocket/blob/master/conn.go#L122

Because the sends are done in separate goroutines, they aren't guaranteed to execute anytime soon โ€“ in particular not before c.ch is eventually closed.

Might I recommend, as JS runs single-threaded, simply to queue messages in a slice rather than a chan? No synchronization necessary, no need to spin up goroutines -> consistent results! Hopefully ;-)

conn.Read only returns io.EOF when websocket connection has been closed

I'm not sure this is actually a bug but I'd like a clarification.

The current behaviour of conn.Read is to read all bytes into the buffer if the buffer is large enough, then return the number of bytes read and a nil error. This should be fine if I've interpreted https://golang.org/pkg/io/#Reader correctly. However, subsequent reads should return 0, io.EOF if there is nothing more to read, and instead it blocks waiting to receive a new frame.

Is this the intended behaviour? It means it's not possible to use ioutil.ReadAll to read a single message, it blocks until the connection is closed.

What type of interface do we want to implement?

We have a choice as to what type of interface we'd like to implement, with each having its pros and cons. I'd like to discuss that here.

The choices so far seem to be:

  • The current master branch's event-driven approach
  • What I originally proposed in #1, our own interface with Send and Receive methods.
  • net.Conn
  • io.ReadWriteCloser

I personally support the idea of creating an interface very similar to net.TCPConn. After all, a TCP connection is conceptually very, very similar to a WebSocket. The primary advantage of this would be that once gopherjs/gopherjs#89 is resolved, WebSocket would be able to be used in the various libraries that desire a net.Conn. The disadvantage is, of course, that we're significantly straying from the underlying interface.

@shurcooL What do you think?

Fails to init websocket if compiled on Windows

From latest commit edfe143

If I gopherjs compile my app on Linux, the generated app.js works fine.

If I gophejs compile the identical code on Windows, the generated app.js fails whilst calling websocket.init

Both generated app.js files are different sizes (is that even right ???)
4,453,535 app.js (windows)
4,420,712 app.js (linux)

In both cases, I am running go1.6, and have removed github.com/gopherjs and then
go get github.com/gopherjs
go get github.com/gopherjs/websocket
Before compiling, so it should be the same gopherjs compiler.

If I compile on Linux, and then scp the generated app.js to the offending Windows machine, and host it from there, it works as expected, (so its not a hosting issue)

Stack trace during a failure on the generated app.js from Windows :

Uncaught Error: system calls not available, see https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md$callDeferred
@ app.js:4$panic
@ app.js:4$packages.syscall.AM.ptr.mustFind
@ app.js:20$packages.syscall.AM.ptr.Addr
@ app.js:20$packages.syscall.LX
@ app.js:20$packages.net.ET
@ app.js:71$packages.net.ES
@ app.js:71$packages.net.$init
@ app.js:71$packages.github.com/gopherjs/websocket.$init
@ app.js:72$packages.main.$init
@ app.js:107$goroutine
@ app.js:4$schedule
@ app.js:4$go
@ app.js:4(anonymous function)
@ app.js:111(anonymous function)
@ app.js:114

The call at $packages.github.com/gopherjs/websocket.$init looks like it is referencing some code in
zsyscall_windows.go, for whatever reason. Hopefully this explains the difference in file sizes of the generated app.js files (although that still looks a bit odd to me)

Its a bit hard to look any deeper than this on this Windows 10 machine that Im stuck on for the day. Its not my machine, and the tools on it are typically abysmal.

I cant be sure exactly when things broke, but I know that 2 weeks ago, I could compile on this Windows machine, and then host the result with no issues. Since then, the only change in the environment was this modification of gopherjs/websocket, from what I can see.

Hope that helps.

Don't import `fmt`

The only reason to import fmt appears to be because of the following line of code:

return fmt.Sprintf("CloseEvent: (%s) (%d) %s", cleanStmt, e.Code, e.Reason)

This could trivially be replaced by

return "CloseEvent: (" + cleanStmt + ") (" + strconv.Itoa(e.Code) + ") " + e.Reason

This would lead to smaller file sizes for the projects using the websocket bindings.

Add WebAssembly support (GOARCH=wasm).

This package should be updated to use the following library so that websocket usage can target wasm and gopherjs:
"github.com/gopherjs/gopherwasm/js"

This will require wrapping callbacks with js.NewEventCallback() (and calling .Release()) and changing *js.Object to js.Value

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.