💾 Archived View for log.aviary.biz › 2022-01-16.gmi captured on 2023-06-16 at 15:56:48. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-03-01)
-=-=-=-=-=-=-
i recently read this post:
"There is no such thing as a static website" by Wesley Aptekar-Cassels
it got me thinking about the meme of "falsehoods programmers believe about $thing", in which an author picks a topic and then proceeds disabuse we readers of our ignorance. i personally liked to be disabused of my ignorance, but i've never performed any assumption annihilation of my own.
thus spake the docs
The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers...
RFC6455: The WebSocket Protocol
on the client (WWW browser) side, the JavaScript looks something like this:
const socket = new WebSocket('ws://localhost:4242/'); socket.addEventListener('open', function (event) { // in this callback, the connection is ready for sending socket.send('from the client to the server') }); socket.addEventListener('message', function (msg) { // this callback is applied to each message from the server console.log('from the server to the client: ', msg.data) });
(i ripped this from MDN)
the server side is basically the same, here written in go:
package main import ( "fmt" "io" "log" "net/http" "golang.org/x/net/websocket" ) func main() { srv := websocket.Server{ Handler: func(ws *websocket.Conn) { if _, err := fmt.Fprint(ws, "from server to client"); err != nil { log.Fatal(err) } msg, err := io.ReadAll(ws) // this blocks on receipt if err != nil { log.Fatal(err) } log.Printf("from client to server: %s", msg) }, } http.Handle("/", srv) log.Fatal(http.ListenAndServe("localhost:4242", nil)) }
or something like that. the interface on both ends gives a programmer the ability to send and receive messages. the abstraction is nice; it gives us a more natural way to implement two-way communication in WWW applications. indeed, WebSockets improves on previous techniques like Server-sent Events.
HTML specification section on Server-sent Events.
aside: SSE is a long polling scheme. the client connects to the server, and the server simply waits until it has events to send. after sending events, the server closes the connection and the client reconnects to restart the cycle. in this scheme, messages can only travel from the server to the client.
this is all speculative nonfiction. i would love to get mail that helps me understand this better.
on the WWW, WebSockets uses TCP. TCP is already a bidirectional transport; both client and server can send(2) and recv(2) on their respective sockets.
when you send(2) on a TCP socket, you tell your operating system to write a TCP packet to memory and then to copy your message as the packet's body. then, the operating system issues an interrupt to your networking device that causes the device to stop what it was doing and read the TCP packet. as the networking device reads the packet, it emits some sequences of voltages on a wire.
when you recv(2) on a TCP socket, you tell your operating system to pause your program's execution and then to arrange for the networking device to interrupt the CPU when it finds a relevant sequence of voltages on its wire.
a CPU can only do one thing at a time! it can multiplex tasks by using other devices (clocks, mostly) to periodically tell it to switch what it was doing.
a networking device can only do one thing at a time! it could multiplex tasks with buffers, but that wouldn't solve the problem of the one physical component (the wire, antenna, whatever) that communicates with the outside world. if that wire has some sequence of voltages on it, the networking device must wait. (i think Ethernet is one protocol that negotiates this waiting)
if we take communication to be the exchange of information between two disparate entities, then communication is necessarily, fundamentally unidirectional. all other schemes are either abstractions or complexities of this unidirectional exchange.