LoginSignup
0
0

Docker-ComposeでGodot用のサーバーを立てようとした話(接続編)

Posted at

これの続きでございます

Godotの資材をアップロードすれば行けるっしょ?

とりあえずPythonでWebSocketのバックエンドをコーディングをして、GodotのWebSocketPeerとの接続が成功すればあとはHTTPSのHTML置き場にアップロードすればチョチョイのパーっしょ。
そう思っていた時期が私にもありました。

とりあえずバックエンド

Python3でWebSocketのサーバーサイドのエコーバックを作る。

ポート番号に深い意味はない。

# coding: utf-8

import asyncio
import websockets
class WebSocketServer:
    def __init__(self, host, port):
        self.host = host
        self.port = port

    async def server(self, ws, path):
        try:
            async for msg in ws:
                print(f"msg from client: {msg}")
                print(f"Got your messaget: {msg}")
                await ws.send(msg)
        except Exception as e:
            print(e)

    async def start(self):
        async with websockets.serve(self.server, self.host, self.port):
            print(f"Server started : {self.host}:{self.port}")
            await asyncio.Future()

    
if __name__ == "__main__":
    print('WebSocketServer start')
    server = WebSocketServer("0.0.0.0", 4545)
    asyncio.run(server.start())

ローカル上で実行
繋がりますね!
image.png

Godotのプロジェクトをブラウザで実行
繋がりますね!
image.png

いざサーバーへ

ここまでは順調に事が運んだ。
だがしかし、Godotの資材をHTTPSに配置し実行してもうんともすんとも言わないのである。
image.png

というわけで、Godotの有識者が集まるDiscordサーバへお邪魔しスレ立てを行いました。
するとこのような回答が。

▼ お返事

「nginx上にシンプルなwebsocket実装のjsファイルを置いて、そこからpython側に通信できるかは試してみましたか?」

そうじゃん!
バケモンにはバケモンをぶつけるのは映画だけ、まずはシンプルな状態でアプローチをかけて問題の切り分けを行うのが鉄則でございます。
Godotもふたを開ければjsファイル吐き出しているっぽいし、簡単なNodeJSで作ってぶつけちゃおう。

使用したテストコード

const WebSocket = require('ws');

const ws = new WebSocket('ws://192.168.3.251:4545');

ws.on('open', function open() {
  console.log('Connected to server');
  ws.send('Hello, server!');
});

ws.on('message', function incoming(message) {
  console.log('Received: %s', message);
});

結果:NG

ってことはサーバー側があかんのとちゃいます?
サーバ側をPythonからNodeJSでやってみる

const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');

const options = {
  key: fs.readFileSync('/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/privkey.pem'),
  cert: fs.readFileSync('/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/cert.pem')
};

const server = https.createServer(options);
const wss = new WebSocket.Server({ server });

wss.on('connection', function connection(ws) {
  console.log('Client connected');
  
  ws.on('message', function incoming(message) {
    console.log('Received: %s', message);
  });
  
  ws.send('Hello, client!');
});

server.listen(4545, '0.0.0.0', function() {
  console.log('Server is listening on port 4545');
});

なんと結果はOKだったんですね。
スクリーンショットとっておけばよかったと後悔

その時梨に電流走る
(あれ?フォントタグ使ってもフォントのサイズ変わらないの!?)

NodeJSでバックエンド作ってしまえば通信が確立するのでは?

とりあえずGodotのプロジェクトをHTML5形式でエクスポートしアップロード
何やら繋がっている模様
image.png
動くやん・・・
そういえばPythonでSSL証明書読み込むやつ書いたっけ?

import ssl
import pathlib
import asyncio
import websockets

# SSL証明書と秘密鍵のパス
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain('/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/cert.pem', '/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/privkey.pem')

# 接続時の処理
async def handle_connection(websocket, path):
    print('Client connected')

    try:
        # メッセージ受信待機
        async for message in websocket:
            print('Received:', message)

            # クライアントにメッセージを返信
            await websocket.send('Server received: ' + message)

    except websockets.exceptions.ConnectionClosedError:
        pass

    finally:
        print('Client disconnected')

# WebSocketサーバーを作成し、SSLで接続を待機
start_server = websockets.serve(
    handle_connection, '0.0.0.0', 4545, ssl=ssl_context
)

# サーバーを起動
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

結果NG(スクリーンショット撮ってなかったなぁ。。。)

とりあえず現状動いているNodeJSをバックエンドの言語に採用することにしました。
Pythonファンの方ごめんなさい!!(Pythonでやりたかったなぁ・・・誰か有識者の方教えてください!)

設定ファイルの整理

NodeJSで作るサーバもどうせならDocker-Composeにまとめる。
Pythonでサーバを作ることはあきらめてないけど、調査は打ち切りで未来の君たちに託す!
とりあえず自分の環境ではこれで動いたというものを置いておく

docker-compose.yml

version: '3'
services:
  nginx:
    image: nginx:latest
    ports:
      - "1010:1010"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl.conf:/etc/nginx/conf.d/ssl.conf
      - ./html:/usr/share/nginx/html
      - /etc/letsencrypt:/etc/letsencrypt:ro
    depends_on:
      - nodeapp  # nginxがnodeappに依存していることを指定
    restart: always 
  nodeapp:
    image: node:latest
    working_dir: /usr/src/app
    ports:
      - "4545:4545"
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt:ro
      - ./server:/usr/src/app
    command: node server.js  # アプリケーションのエントリーポイントを指定するコマンド
    restart: always 
networks:
  default:
    driver: bridge

nginx.conf

events {}
http {
    include /etc/nginx/conf.d/*.conf;
}

ssl.conf

server {
    listen 1010 ssl;
    server_name [NoIPあたりで取得したドメイン];

    ssl_certificate /etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    # Cross-Origin-Embedder-Policyヘッダーを設定
    add_header Cross-Origin-Embedder-Policy "require-corp";

    # Cross-Origin-Opener-Policyヘッダーを設定
    add_header Cross-Origin-Opener-Policy "same-origin";
    
    include       mime.types;
    default_type  application/octet-stream;
    
    types {
        text/javascript js;
        application/javascript js;
    }
    
    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

server.js

const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');

const options = {
  key: fs.readFileSync('/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/privkey.pem'),
  cert: fs.readFileSync('/etc/letsencrypt/live/[NoIPあたりで取得したドメイン]/cert.pem')
};

const server = https.createServer(options);
const wss = new WebSocket.Server({ server });

wss.on('connection', function connection(ws) {
  console.log('Client connected');
  
  ws.on('message', function incoming(message) {
    console.log('Received: %s', message);
  });
  
  ws.send('Hello, client!');
});

server.listen(4545, '0.0.0.0', function() {
  console.log('Server is listening on port 4545');
});

ディレクトリ構成

root/
┣docker-compose.yml
┣nginx.conf
┣ssl.conf
┣server/
┃┗server.js
┗html/
 ┗Godotがエクスポートした資材を丸ごと配置

謎はまだまだ!調べないといけないこと

じつはほかにも気になっていることがあって、これは仕様なのかどうなのかがわからないんでござ。
今後GodotのDiscordサーバーにスレ立てするかもしれません。

  1. ブラウザ上に表示されたGodotの画面から別のタブを新しく開き、新しいタブをアクティブ状態にするとWebSocket通信を停止してしまう
  2. そもそもこのエラーや警告は何?
    image.png
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0