Error Reading Ws. Error Reading Websocket: Read Tcp -> Use of Closed Network Connection

How to Use Websockets in Golang: Best Tools and Step-by-Step Guide

Sending a message and getting an instant response without refreshing the folio is something we have for granted. But in the past, enabling real-time functionality was a real claiming for developers. The programmer community has come up a long style from HTTP long polling and AJAX and has finally found a solution for building truly real-fourth dimension apps.

This solution comes in the form of WebSockets, which make it possible to open an interactive session between a user's browser and a server. WebSockets allow a browser to send messages to a server and receive event-driven responses without having to poll the server for a reply.

For now, WebSockets are the number one solution for edifice real-fourth dimension applications: online games, instant messengers, tracking apps, and so on. This guide explains how WebSockets operate and shows how we tin build WebSocket applications in the Go programming linguistic communication. Nosotros also compare the nigh pop WebSocket libraries so yous tin can choose the best one for your needs.

Read also: Best Practices for Speeding Upwards JSON Encoding and Decoding in Go

Network sockets vs WebSockets

To detect how to become started with WebSockets in the Become, let'south begin by drawing the line between network sockets and WebSockets.

Network socket

A network socket, or simply a socket, serves as an internal endpoint for exchanging data between applications running on the same estimator or on unlike computers on the same network.

Sockets are a primal part of Unix and Windows-based operating systems, and they make it easier for developers to create network-enabled software. Instead of constructing network connections from scratch, app developers tin can include sockets in their programs. Since network sockets are used for several network protocols (HTTP, FTP, etc.), multiple sockets can be used simultaneously.

Sockets are created and used with a set of function calls defined by a socket's application programming interface (API).

There are several types of network sockets:

Datagram sockets (SOCK_DGRAM), also known as connectionless sockets, use the User Datagram Protocol (UDP). Datagram sockets support a bidirectional period of messages and preserve record boundaries.

Stream sockets (SOCK_STREAM), also known as connectedness-oriented sockets, use the Transmission Control Protocol (TCP), Stream Control Transmission Protocol (SCTP), or Datagram Congestion Command Protocol (DCCP). These sockets provide a bidirectional, reliable, sequenced, and unduplicated flow of data with no record boundaries.

Raw sockets (or raw IP sockets) are typically available in routers and other networking equipment. These sockets are normally datagram-oriented, although their exact characteristics depend on the interface provided by the protocol. Raw sockets are not used past virtually applications. They're provided to support the development of new communication protocols and to provide admission to more esoteric facilities of existing protocols.

Socket communication

Each network socket is identified past the address, which is a triad of a transport protocol, IP accost, and port number.

There are ii major protocols for communicating between hosts: TCP and UDP. Let'due south encounter how your app tin connect to TCP and UDP sockets.

  • Connecting to a TCP socket

To establish a TCP connexion, a Go customer uses the DialTCP function in the net packet. DialTCP returns a TCPConn object. When a connection is established, the client and server begin exchanging information: the customer sends a request to the server through a TCPConn object, the server parses the request and sends a response, and the TCPConn object receives the response from the server.

tcp socket

This connectedness remains valid until the client or server closes it. The functions for creating a connection are as follows:

Customer side:

               // init    tcpAddr, err := net.ResolveTCPAddr(resolver, serverAddr)    if err != nil {         // handle mistake    }    conn, err := net.DialTCP(network, nil, tcpAddr)    if err != nil {            // handle error    }     // ship message     _, err = conn.Write({message})    if err != nix {         // handle fault    }     // receive message    var buf [{buffSize}]byte    _, err := conn.Read(buf[0:])    if err != zilch {         // handle error    }            

Server side:

              // init    tcpAddr, err := net.ResolveTCPAddr(resolver, serverAddr)        if err != nil {            // handle mistake        }            listener, err := net.ListenTCP("tcp", tcpAddr)     if err != nil {         // handle mistake     }          // listen for an incoming connection     conn, err := listener.Accept()     if err != nil {         // handle error     }          // send bulletin     if _, err := conn.Write({message}); err != nil {         // handle error     }         // receive message     buf := make([]byte, 512)     n, err := conn.Read(buf[0:])     if err != zip {         // handle fault     }            
  • Connecting to a UDP socket

In dissimilarity to a TCP socket, with a UDP socket, the client just sends a datagram to the server. At that place's no Have function, since the server doesn't demand to accept a connexion and just waits for datagrams to make it.

udp socket

Other TCP functions accept UDP counterparts; just supersede TCP with UDP in the functions to a higher place.

Client side:

              // init     raddr, err := internet.ResolveUDPAddr("udp", address)     if err != nil {         // handle error     }             conn, err := cyberspace.DialUDP("udp", nix, raddr)     if err != nil {         // handle error     }         .......      // transport message     buffer := brand([]byte, maxBufferSize)     due north, addr, err := conn.ReadFrom(buffer)     if err != nil {         // handle error     }          .......                 // receive bulletin     buffer := make([]byte, maxBufferSize)     n, err = conn.WriteTo(buffer[:northward], addr)     if err != nothing {         // handle error     }            

Server side:

                  // init     udpAddr, err := net.ResolveUDPAddr(resolver, serverAddr)     if err != nil {         // handle error     }          conn, err := cyberspace.ListenUDP("udp", udpAddr)     if err != nil {         // handle error     }         .......     // send message     buffer := make([]byte, maxBufferSize)     due north, addr, err := conn.ReadFromUDP(buffer)     if err != nix {         // handle error     }          .......     // receive message     buffer := make([]byte, maxBufferSize)     northward, err = conn.WriteToUDP(buffer[:n], addr)     if err != zippo {         // handle error     }            

What WebSockets are

The WebSocket communication package provides a full-duplex communication aqueduct over a single TCP connection. That means that both the customer and the server tin simultaneously transport data whenever they need without any request.

WebSockets are a expert solution for services that require continuous information exchange – for instance, instant messengers, online games, and real-fourth dimension trading systems. Yous tin notice complete data about the WebSocket protocol in the Cyberspace Engineering Job Force (IETF) RFC 6455 specification.

WebSocket connections are requested by browsers and are responded to by servers, after which a connection is established. This process is often called a handshake. The special kind of header in WebSockets requires only one handshake between a browser and server for establishing a connection that will remain active throughout its lifetime.

The WebSocket protocol uses port 80 for an unsecure connection and port 443 for a secure connection. The WebSocket specification determines which compatible resource identifier schemes are required for the ws (WebSocket) and wss (WebSocket Secure) protocols.

WebSockets solve many of the headaches of developing existent-time web applications and have several benefits over traditional HTTP:

  • The lightweight header reduces data transmission overhead.
  • Just one TCP connectedness is required for a single web customer.
  • WebSocket servers can push button information to spider web clients.

how websockets work

The WebSocket protocol is relatively unproblematic to implement. It uses the HTTP protocol for the initial handshake. Later on a successful handshake, a connectedness is established and the WebSocket essentially uses raw TCP to read/write data.

This is what a client request looks similar:

                Become /chat HTTP/1.1     Host: server.example.com     Upgrade: websocket     Connection: Upgrade     Sec-WebSocket-Primal: x3JJHMbDL1EzLkh9GBhXDw==     Sec-WebSocket-Protocol: chat, superchat     Sec-WebSocket-Version: 13     Origin: http://instance.com            


And here'due south the server response:

                  HTTP/1.1 101 Switching Protocols     Upgrade: websocket     Connection: Upgrade     Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=     Sec-WebSocket-Protocol: chat            

How to create a WebSocket app in Go

To write a uncomplicated WebSocket echo server based on the net/http library, you need to:

  1. Initiate a handshake
  2. Receive information frames from the client
  3. Send data frames to the client
  4. Close the handshake

First, allow's create an HTTP handler with a WebSocket endpoint:

              // HTTP server with WebSocket endpoint         func Server() {         http.HandleFunc("/", func(westward http.ResponseWriter, r *http.Asking) {             ws, err := NewHandler(w, r)             if err != zip {                  // handle error             }             if err = ws.Handshake(); err != goose egg {                 // handle fault             }         …            

And then initialize the WebSocket structure.

The initial handshake request always comes from the client. Once the server has defined a WebSocket asking, it needs to answer with a handshake response.

Behave in mind that you can't write the response using the http.ResponseWriter, since information technology volition close the underlying TCP connectedness once you start sending the response.

So you demand to apply HTTP hijacking. Hijacking allows you lot to accept over the underlying TCP connection handler and bufio.Writer. This gives you the possibility to read and write data without closing the TCP connection.

              // NewHandler initializes a new handler         func NewHandler(w http.ResponseWriter, req *http.Asking) (*WS, error) {         hj, ok := w.(http.Hijacker)         if !ok {             // handle error         }                  ..... }            

To complete the handshake, the server must respond with the appropriate headers.

              // Handshake creates a handshake header     func (ws *WS) Handshake() error {                  hash := func(key string) string {             h := sha1.New()             h.Write([]byte(key))             h.Write([]byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))          return base64.StdEncoding.EncodeToString(h.Sum(nil))         }(ws.header.Get("Sec-WebSocket-Key"))       ..... }            

"Sec-WebSocket-fundamental" is generated randomly and is Base64-encoded. The server needs to append this primal to a fixed string after accepting a request. Assume you have the x3JJHMbDL1EzLkh9GBhXDw== key. In this case, you can use SHA-ane to compute the binary value and use Base64 to encode it. You'll get HSmrc0sMlYUkAGmm5OPpG2HaGWk=. Utilise this as the value of the Sec-WebSocket-Accept response header.

Transferring the data frame

When the handshake has been successfully completed, your app can read and write data from and to the client. The WebSocket specification defines a specific frame format that's used between a client and a server. Here is the bit pattern of the frame:

The bit pattern of the frame

Use the following code to decode the client payload:

              // Recv receives information and returns a Frame     func (ws *WS) Recv() (frame Frame, _ error) {         frame = Frame{}         caput, err := ws.read(2)         if err != zero {             // handle mistake         }            

In turn, these lines of code permit for encoding data:

              // Transport sends a Frame     func (ws *WS) Send(fr Frame) error {         // make a piece of bytes of length 2         data := make([]byte, 2)              // Save fragmentation & opcode data in the first byte         data[0] = 0x80 | fr.Opcode         if fr.IsFragment {             data[0] &= 0x7F         }         .....            

Closing a handshake

A handshake is airtight when 1 of the parties sends a close frame with a shut status equally the payload. Optionally, the party sending the close frame can send a close reason in the payload. If closing is initiated by the client, the server should transport a corresponding close frame in response.

              // Close sends a close frame and closes the TCP connection func (ws *Ws) Close() error {     f := Frame{}     f.Opcode = 8     f.Length = 2     f.Payload = make([]byte, 2)     binary.BigEndian.PutUint16(f.Payload, ws.condition)     if err := ws.Ship(f); err != nil {         render err     }     render ws.conn.Shut() }            

List of WebSocket libraries

There are several third-political party libraries that ease developers' lives and profoundly facilitate working with WebSockets.

  • STDLIB ( x/net/websocket)

This WebSocket library is part of the standard Become library. It implements a customer and server for the WebSocket protocol, as described in the RFC 6455 specification. It doesn't need to exist installed and has good official documentation. On the other manus, it however lacks some features that can be found in other WebSocket libraries. Golang WebSocket implementations in the /ten/internet/websocket package do non allow users to reuse I/O buffers between connections in a articulate way.

Let's check how the STDLIB bundle works. Hither's an example of code for performing basic functions like creating a connection and sending and receiving letters.
Start of all, to install and use this library, you should add this line of lawmaking:

import "golang.org/ten/net/websocket"

Customer side:

                  // create connection     // schema can exist ws:// or wss://     // host, port – WebSocket server     conn, err := websocket.Dial("{schema}://{host}:{port}", "", op.Origin)     if err != nil {         // handle error     }      defer conn.Close()              .......       // send message         if err = websocket.JSON.Send(conn, {bulletin}); err != nil {          // handle error     }               .......         // receive message     // messageType initializes some type of bulletin     message := messageType{}     if err := websocket.JSON.Receive(conn, &message); err != nil {           // handle error     }           .......            

Server side:

                  // Initialize WebSocket handler + server     mux := http.NewServeMux()         mux.Handle("/", websocket.Handler(func(conn *websocket.Conn) {             func() {                 for {                                      // practise something, receive, transport, etc.                 }             }             .......             // receive message     // messageType initializes some type of message     message := messageType{}     if err := websocket.JSON.Receive(conn, &message); err != nil {         // handle error     }         .......          // send bulletin     if err := websocket.JSON.Ship(conn, message); err != nil {         // handle error     }             ........            
  • GORILLA

The WebSocket parcel in the Gorilla web toolkit boasts a complete and tested implementation of the WebSocket protocol besides equally a stable parcel API. The WebSocket package is well-documented and easy to use. You tin find documentation on the official Gorilla website.

Installation:

              become get github.com/gorilla/websocket Examples of code Client side:  // init     // schema – can be ws:// or wss://     // host, port – WebSocket server       u := url.URL{         Scheme: {schema},         Host:   {host}:{port},         Path:   "/",     }     c, _, err := websocket.DefaultDialer.Punch(u.Cord(), nil)     if err != zip {         // handle fault     }         .......         // transport message     err := c.WriteMessage(websocket.TextMessage, {message})     if err != nil {         // handle error     }           .......           // receive bulletin     _, message, err := c.ReadMessage()     if err != goose egg {         // handle error     }         .......            

Server side:

                // init     u := websocket.Upgrader{}     c, err := u.Upgrade(w, r, nil)     if err != nil {         // handle mistake     }         .......         // receive message     messageType, message, err := c.ReadMessage()     if err != nil {         // handle error     }         .......            // send message     err = c.WriteMessage(messageType, {message})     if err != nil {         // handle error     }         .......            

Read as well: What projects should you lot use Get for?

  • Gobwas

​​​​This tiny WebSocket package has a powerful list of features, such equally zero-copy upgrading and a low-level API that allows for edifice custom package handling logic. Gobwas requires no intermediate allocations during I/O. It also boasts high-level wrappers and helpers around the API in the wsutil packet, allowing developers to start fast without digging into the internals of the protocol. This library has a flexible API, but it comes at the toll of usability and clarity.

You can cheque the GoDoc website for documentation. You can install Gobwas past including the following line of code:

go become github.com/gobwas/ws

Client side:

                  // init     // schema – can be ws or wss     // host, port – ws server     conn, _, _, err := ws.DefaultDialer.Dial(ctx, {schema}://{host}:{port})     if err != nil {         // handle mistake     }         .......     // ship message     err = wsutil.WriteClientMessage(conn, ws.OpText, {message})     if err != nil {         // handle error     }              .......     // receive message         msg, _, err := wsutil.ReadServerData(conn)     if err != nil {         // handle fault     }         .......            

Server side:

                              // init     listener, err := internet.Listen("tcp", op.Port)     if err != zero {         // handle error     }     conn, err := listener.Accept()     if err != nil {         // handle error     }     upgrader := ws.Upgrader{}     if _, err = upgrader.Upgrade(conn); err != nix {         // handle fault     }         .......     // receive message     for {           reader := wsutil.NewReader(conn, ws.StateServerSide)          _, err := reader.NextFrame()          if err != nil {              // handle error          }          information, err := ioutil.ReadAll(reader)          if err != nil {              // handle error          }             .......     }            .......     // send bulletin     msg := "new server message"     if err := wsutil.WriteServerText(conn, {message}); err != null {         // handle error     }         .......            
  • GOWebsockets

This tool offers a broad range of easy-to-use features. It allows for concurrency control, data compression, and setting request headers. GOWebsockets supports proxies and subprotocols for emitting and receiving text and binary information. Developers tin can also enable or disable SSL verification.

Yous tin can find documentation for and examples of how to use GOWebsockets on the GoDoc website and on the project's GitHub page. Install the package by adding the following line of code:

become become github.com/sacOO7/gowebsocket

Client side:

                  // init     // schema – tin can be ws or wss     // host, port – ws server     socket := gowebsocket.New({schema}://{host}:{port})     socket.Connect()         .......       // ship message     socket.SendText({bulletin})     or     socket.SendBinary({message})         .......     // receive message     socket.OnTextMessage = func(message string, socket gowebsocket.Socket) {         // hande received bulletin     };     or     socket.OnBinaryMessage = func(data [] byte, socket gowebsocket.Socket) {         // hande received bulletin     };           .......            

Server side:

                  // init     // schema – can be ws or wss     // host, port – ws server     conn, _, _, err := ws.DefaultDialer.Dial(ctx, {schema}://{host}:{port})     if err != null {         // handle error     }         .......             // send message     err = wsutil.WriteClientMessage(conn, ws.OpText, {message})     if err != nil {         // handle error     }         .......            // receive message         msg, _, err := wsutil.ReadServerData(conn)     if err != nil {         // handle fault     }            

Comparing existing solutions

We've described four of the most widely used WebSocket libraries for Golang. The table below contains a detailed comparison of these tools.

websocket libraries

To better analyze their operation, we also conducted a couple of benchmarks.

Read too: Monitoring the Performance of Your Go Application: Why and How You Should Exercise Information technology

The results are the following:

Benchmark tests

  • Every bit you can run across, Gobwas has a significant reward over other libraries. It has fewer allocations per operation and uses less memory and time per allocation. Plus, it has zero I/O resource allotment. As well, Gobwas has all the methods you need to create WebSocket customer–server interactions and receive message fragments. You can too employ it to hands work with TCP sockets.
  • If you really don't similar Gobwas, yous can utilize Gorilla. It'south quite uncomplicated and has almost still features. You can also utilize STDLIB, but it's not as good in production because it lacks many necessary features and, as y'all can encounter in the benchmarks, offers weaker performance. GOWebsocket is about the same as STDLIB. Merely if you lot need to quickly build a image or MVP, it can be a reasonable choice.

Besides these tools, there are also several alternative implementations that allow you to build powerful streaming solutions. Among them are:

  • go-socket.io

  • Apache Austerity

  • gRPC

  • Package rpc

The constant evolution of streaming technologies and the availability of well-documented tools such as WebSockets arrive easy for developers to create truly real-time applications. Write us if you demand advice on or help with creating a real-time app using WebSockets. We hope this tutorial helped you a lot.

Remember those Facebook reactions? Well, we aren't Facebook but we love reactions too. They tin can give us valuable insights on how to better what we're doing. Would y'all tell us how yous feel about this article?

What to observe what helps united states of america create robust apps?

That'southward a proficient idea.

Bank check our expertise.

leonuntler.blogspot.com

Source: https://yalantis.com/blog/how-to-build-websockets-in-go/

0 Response to "Error Reading Ws. Error Reading Websocket: Read Tcp -> Use of Closed Network Connection"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel