On Julia pre 0.7, see an earlier version of this repository.
(v0.7) pkg>add WebSockets julia> using WebSockets julia> varinfo(WebSockets) help?> serve help?> WebSockets.open julia> cd(joinpath((WebSockets |> Base.pathof |> splitdir), "..", "examples")) julia> readdir() julia> include("chat_explore.jl")
Open a client side connection
Client side websockets are created by calling
WebSockets.open (with a server running somewhere). Example (you can run this in a second REPL, or in the same):
julia> cd(joinpath((WebSockets |> Base.pathof |> splitdir), "..", "examples")) julia> include("client_repl_input.jl")
writeguarded instead of
write for more effective debugging.
Debugging server side connections
Server side websockets are asyncronous tasks, which makes debugging harder. The error messages may not spill into the REPL. There are two interfaces to starting a server which includes a websocket handling function:
Error messages are directed to a channel. See inline docs: ?Websockets.serve.
Error messages are by default sent as messages to the client. This is not good practice if you're serving pages to the internet, but nice while developing locally.
What is nice with WebSockets.jl?
Some packages rely on WebSockets for communication. You can also use it directly:
- reading and writing between entities you can program or know about
- low latency, high speed messaging
- implementing your own 'if X send this, Y do that' subprotocols
- registered websocket subprotocols for e.g. remote controlled hardware
- heartbeating, relaying user interaction to backend simulations
- build a network including browser clients
- convenience functions for gatekeeping
- putting http handlers and websocket coroutines ('handlers') in the same process can be a security advantage. It is good practice to modify web page responses to include time-limited tokens in the wsuri.
WebSockets are well suited for user interactions via a browser or cross-platform applications like electron. Workload and development time can be moved off Julia resources, error checking code can be reduced. Use websockets to pass arguments between compiled functions on both sides; it has both speed and security advantages over passing code for evaluation.
The /logutils folder contains some specialized logging functionality that is quite fast and can make working with multiple asyncronous tasks easier. See /benchmark code for how to use. Logging may be moved entirely out of WebSockets.jl in the future.
What are the main downsides to using WebSockets.jl directly?
- Logging. We need customizable and very fast logging for building networked applications.
- Compression is not implemented.
- Possibly non-compliant proxies on the internet, company firewalls.
- 'Warm-up', i.e. compilation when a method is first used. Warm-up is excluded from current benchmarks.
- Garbage collection, which increases message latency at semi-random intervals. See benchmark plots.
- If a connection is closed improperly, the connection task will throw uncaught ECONNRESET and similar messages.
- TCP quirks, including 'warm-up' time with low transmission speed after a pause. Heartbeats can alleviate.
readis a blocking function, you can easily end up reading indefinitely from any side of the connection. See the `close function code for an example of non-blocking read with a timeout.
Errors after updating?
The introduction of client side websockets to this package in version 0.5.0 may require changes in your code:
WebSocket.idfield is no longer supported. You can generate unique counters by code similar to 'bencmark/functions_open_browsers.jl' COUNTBROWSER.
- You may want to modify you error handling code. Examine WebSocketsClosedError.message.
- You may want to use
writeguardedto save on error handling code.
WebSockets.WebsocketHandler(or just pass a function without wrapper)
HTTP.HandlerFunction(or just pass a function without wrapper)
You may also want to consider using
are compatible with both of the types above.
:::::::::::::::: :: :: :: Made at :: :: :: :::::::::::::::: :: Recurse Center ::::::::::::::::