1.10.15.12. fejezet, WebSocket

Az alábbi program egy chat kliens. Az App.tsx:

import React, { Component, useState } from 'react';
 
import {
    FlatList,
    StyleSheet,
    View,
    Text,
} from 'react-native';
import WebSocketApp from './WebSocketApp';
 
type MainViewState = {
    messages: string[];
}
 
class App extends Component<MainViewState> {
    state: MainViewState = { messages: [''] };
 
    constructor(props: MainViewState | Readonly<MainViewState>) {
        super(props);
 
        let webSocketApp: WebSocketApp = new WebSocketApp();
        const callBack = (e: any) => {
            let msgs = this.state.messages;
            if (e.data instanceof ArrayBuffer) {
                const str = new TextDecoder().decode(new Uint8Array(e.data));
                console.log('ArrayBuffer message: ' + str);
                msgs.unshift(str);
            } else {
                console.log('Text message: ' + JSON.stringify(e));
                msgs.unshift(e.data);
 
            }
            this.setState({ messages: msgs });
        }
        webSocketApp.startWebSocket(callBack);
    }
 
    render() {
        return (
            <View style={styles.container}>
                <FlatList
                    data={this.state.messages}
                    renderItem={({ item }) => (
                        <Text>{item}</Text>
                    )}
                    keyExtractor={(item) => item}
                />
            </View>
        );
    };
}
 
const styles = StyleSheet.create({
    container: {
        flex: 1, padding: 20
    },
});
 
export default App;

A TextDecoder osztály eléréséhez a tsconfig.json-ba be kell venni a következőket:

{
...
  "compilerOptions": {
...
    "lib": [
      "es2017",
      "dom"
    ]
...
  }
}

A WebSocketApp.tsx az alábbi:

class WebSocketApp {
  public startWebSocket(onMessageCallBack: (e: any) => void) {
    var ws = new WebSocket('ws://192.168.1.13:8082?client=pzoli');
 
    ws.onopen = () => {
      ws.send('Hello from WS client!');  // send a message
    };
 
    ws.onmessage = (e) => {
      onMessageCallBack(e);
    };
 
    ws.onerror = (e) => {
      console.log('Error: ' + JSON.stringify(e));
    };
 
    ws.onclose = (e) => {
      console.log('onClose', e.code, e.reason);
    };
  };
}
 
export default WebSocketApp;

Böngésző kliens pedig a következő:

<!doctype html>
<html>
<head>
<style>
    textarea { vertical-align: bottom; }
    #output { overflow: auto; }
    #output > p { overflow-wrap: break-word; }
    #output span { color: blue; }
    #output span.error { color: red; }
</style>
</head>
<body>
<h2>WebSocket Test</h2>
<textarea cols=60 rows=6>
HelpMe
</textarea>
<button>send</button>
<div id=output></div>
<script>
 
    var button = document.querySelector("button"),
        output = document.querySelector("#output"),
        textarea = document.querySelector("textarea"),
 
    wsUri = "ws://localhost:8082?client=pappz";
    websocket = new WebSocket(wsUri);
 
    button.addEventListener("click", onClickButton);
 
    websocket.onopen = function (e) {
        writeToScreen("CONNECTED");
    };
 
    websocket.onclose = function (e) {
        writeToScreen("DISCONNECTED");
    };
 
    websocket.onmessage = function (e) {
        if (e.data instanceof Blob) {
          reader = new FileReader();
          reader.onload = () => {        
            writeToScreen("<span>RESPONSE: " + reader.result + "</span>");
          }
          reader.readAsText(e.data);
        } else {
          writeToScreen("<span>RESPONSE: " + e.data + "</span>");
        }
    };
 
    websocket.onerror = function (e) {
        writeToScreen("<span class=error>ERROR:</span> " + e.data);
    };
 
    function doSend(message) {
        writeToScreen("SENT: " + message);
        websocket.send(message);
    }
 
    function writeToScreen(message) {
        output.insertAdjacentHTML("afterbegin", "<p>" + message + "</p>");
    }
 
    function onClickButton() {
		var jsonShowMsg = textarea.value;
		doSend(jsonShowMsg);
        textarea.value = "";
        textarea.focus();
    }
</script>
</body>
</html>

A NodeJS szerver pedig a következő:

const WebSocket = require('ws');
const url = require('url');
/* HTTPS Server (NOT WORK With SelfSigned certs)
const fs = require('fs');
const https = require('https');
const server = new https.createServer({
    cert: fs.readFileSync('cert.pem'), //fullchain.pem in LetsEncrypt /etc/letsencrypt/live/[sitename]/
    key: fs.readFileSync('key.pem') //privkey.pem in LetsEncrypt /etc/letsencrypt/live/[sitename]/
});
//*/
//*  HTTP Server
const http = require('http');
const server = new http.createServer();
//*/
 
const wss = new WebSocket.Server({ server });
var msg;
var clients = new Set();
 
wss.on('connection', function connection(ws, req) {
    clients.add(ws);
    const parameters = url.parse(req.url, true);
    console.log("Params: ", JSON.stringify(parameters));
    console.log("Client:", parameters.query.client);
    ws.userName = parameters.query.client;
    ws.on('message', function incoming(message) {
        msg = message;
        console.log('received: %s', msg);
        wss.clients.forEach(function (client) {
            if (client != ws && client.readyState == WebSocket.OPEN) {
                client.send(ws.userName + ": " + msg);
            }
        });
    });
    ws.on('close', function () {
        clients.delete(ws);
        console.log('disconnected');
    });
 
    ws.send('Hello ' + ws.userName + '! Chat room is working.');
});
 
server.listen(8082);