[Перевод] Создание системы чата с помощью Go и ReactJS (2)

Go

Полный код этого раздела:GitHub

Эта статья является второй частью этой серии статей об использовании ReactJS и Go для создания приложения чата. Вы можете найти часть 1 здесь -Инициализировать настройки

Теперь, когда мы установили базовый интерфейс и серверную часть, нам нужно улучшить некоторые функции.

В этом разделе мы реализуем сервер на основе WebSocket.

К концу этой серии руководств у нас будет интерфейсное приложение, которое может взаимодействовать с серверной частью в двух направлениях.

Служить

мы можем использоватьgithub.com/gorilla/websocketПакет для настройки службы WebSocket и обработки операций чтения и записи на подключении Websocket.

Это должно быть в нашемbackend/каталог, чтобы установить его, выполнив эту команду:

$ go get github.com/gorilla/websocket

После того, как мы успешно установили этот пакет, мы можем приступить к созданию нашего веб-сервиса. Сначала мы создаем очень простойnet/httpСлужить:

package main

import (
    "fmt"
    "net/http"
)

func setupRoutes() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Simple Server")
    })
}

func main() {
    setupRoutes()
    http.ListenAndServe(":8080", nil)
}

позвонивgo run main.goзапустить службу, которая будет слушатьhttp://localhost:8080. Если вы откроете это соединение в браузере, вы увидите выводSimple Server.

Протокол веб-сокета

Прежде чем мы начнем писать код, нам нужно понять теорию.

WebSockets могут обмениваться данными в дуплексном режиме через TCP-соединение. Это позволяет нам отправлять и прослушивать сообщения через один сокет TCP, избегая необходимости опрашивать веб-сервер для связи, который выполняет процесс квитирования TCP для каждой операции опроса.

Веб-сокеты значительно уменьшают пропускную способность сети, необходимую приложению, и позволяют нам поддерживать большое количество клиентов на одном экземпляре сервера.

соединять

У WebSockets определенно есть некоторые недостатки, которые стоит учитывать. Например, после введения состояния оно становится более сложным при масштабировании приложения на несколько экземпляров.

В этом сценарии следует учитывать и другие случаи, например сохранение состояния в брокере сообщений или в кэше базы данных/памяти.

выполнить

При реализации службы WebSocket нам необходимо создать конечную точку, а затем обновить соединение конечной точки со стандартного HTTP на WebSocket.

К счастью,gorilla/websocketПакет предоставляет функциональные возможности, необходимые для простого обновления соединений HTTP до соединений WebSocket.

Примечание. Вы можете ознакомиться с официальным протоколом WebSocket для получения дополнительной информации:RFC-6455

Создайте сервер WebSocket

Теперь, когда вы поняли теорию, давайте посмотрим, как применить ее на практике. Создаем новую конечную точку/ws, начнем со стандартаhttpКонечные точки преобразуются вwsконечная точка.

Эта конечная точка сделает 3 вещи, проверит входящий HTTP-запрос и вернетtrueчтобы открыть нашу конечную точку для клиента. Затем мы используем определенныйupgraderОбновление до подключения WebSocket.

Наконец, мы начнем прослушивать входящие сообщения, затем распечатывать их и передавать обратно по тому же соединению. Это позволяет нам аутентифицировать внешнее соединение и отправлять/получать сообщения от только что созданной конечной точки WebSocket:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

// 我们需要定义一个 Upgrader
// 它需要定义 ReadBufferSize 和 WriteBufferSize
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
  WriteBufferSize: 1024,

  // 可以用来检查连接的来源
  // 这将允许从我们的 React 服务向这里发出请求。
  // 现在,我们可以不需要检查并运行任何连接
  CheckOrigin: func(r *http.Request) bool { return true },
}

// 定义一个 reader 用来监听往 WS 发送的新消息
func reader(conn *websocket.Conn) {
    for {
    // 读消息
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
    // 打印消息
        fmt.Println(string(p))

        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println(err)
            return
        }

    }
}

// 定义 WebSocket 服务处理函数
func serveWs(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.Host)

  // 将连接更新为 WebSocket 连接
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
  }

  // 一直监听 WebSocket 连接上传来的新消息
    reader(ws)
}

func setupRoutes() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Simple Server")
  })

  // 将 `/ws` 端点交给 `serveWs` 函数处理
    http.HandleFunc("/ws", serveWs)
}

func main() {
    fmt.Println("Chat App v0.01")
    setupRoutes()
    http.ListenAndServe(":8080", nil)
}

Если нет проблем, мы используемgo run main.goдля запуска службы.

клиент

Теперь, когда служба настроена, нам нужно что-то, с чем можно взаимодействовать. Здесь в игру вступает наш интерфейс ReactJS.

Давайте постараемся максимально упростить клиент и определимapi/index.jsФайл, он будет содержать код подключения WebSocket.

// api/index.js
var socket = new WebSocket("ws://localhost:8080/ws");

let connect = () => {
  console.log("Attempting Connection...");

  socket.onopen = () => {
    console.log("Successfully Connected");
  };

  socket.onmessage = msg => {
    console.log(msg);
  };

  socket.onclose = event => {
    console.log("Socket Closed Connection: ", event);
  };

  socket.onerror = error => {
    console.log("Socket Error: ", error);
  };
};

let sendMsg = msg => {
  console.log("sending msg: ", msg);
  socket.send(msg);
};

export { connect, sendMsg };

Итак, в приведенном выше коде мы определяем 2 функции, которые затем экспортируем. соответственноconnect()а такжеsendMsg(msg).

Первая функция,connect()функция, которая подключается к конечной точке WebSocket и прослушивает, например, с помощьюonopenТакие события, как успешное подключение. Если он обнаруживает какие-либо проблемы, такие как закрытые сокеты соединения или ошибки, он выводит эти проблемы в консоль браузера.

вторая функция,sendMsg(msg)функция, которая позволяет нам использоватьsocket.send()Отправляйте сообщения из внешнего интерфейса в бэкэнд через соединение WebSocket.

Теперь обновляем в проекте ReactApp.jsфайл, добавьте паруconnect()позвонить и создать триггерsendMsg()функциональный<button />элемент.

// App.js
import React, { Component } from "react";
import "./App.css";
import { connect, sendMsg } from "./api";

class App extends Component {
  constructor(props) {
    super(props);
    connect();
  }

  send() {
    console.log("hello");
    sendMsg("hello");
  }

  render() {
    return (
      <div className="App">
        <button onClick={this.send}>Hit</button>
      </div>
    );
  }
}

export default App;

использоватьnpm startПосле успешной компиляции мы можем увидеть кнопку в браузере, и если мы откроем консоль браузера, мы также увидим, что успешно подключенный сервис WebSocket работает наhttp://localhost:8080.

Вопрос - что происходит при нажатии на эту кнопку? Какой вывод вы видите в консоли браузера и консоли бэкэнда?

Суммировать

На этом вторая часть этой серии заканчивается. Нам удалось создать очень простую службу WebSocket, которая повторяет любое посланное ей сообщение.

Это важный шаг в разработке приложения, и теперь, когда у нас есть базовая структура, мы можем начать думать о реализации основных функций чата и сделать приложение более полезным!

Далее: Часть 3 -Фронтальная реализация


оригинал:учебник edge.net/projects/eat…

автор:Elliot ForbesПереводчик:щелк-щелкКоррезирование:polaris1119

Эта статья написанаGCTTоригинальная компиляция,Перейти на китайский языкЧесть запуска