はじめに
この記事では、ネットワークアプリケーション(私の場合はゲーム)をソーシャルネットワークと統合した経験を共有したいと思います。 可能であれば、サードパーティのソリューションに頼らないようにするため、ネットワーク部分は
Unity3Dが提供するもの、つまり低レベル部分(
LLAPI )を使用する
Unetで開発されました。 クライアントの
NetworkClientは、リモートサーバーの
NetworkServerに接続します。 ゲームサーバーも
Unity3Dで記述されてい
ます 。 このようなバンドルで動作しますが、
Unetの詳細な知識が必要ですが、否定できない利点があります。
問題
そして、今度はソーシャルにアプリケーションを投稿します。 ネットワーク。 APIソーシャルを接続することにより。 ネットワーク、ソーシャルでアプリケーションを設定します。 ネットワーク、
WebGlアセンブリをコンパイルし、サーバーにゲームを投稿しました。 アプリケーションの最初の起動ですぐにエラーが明らかになりました
。WebGlアセンブリは通常の
Socketを開くことができず、
WebSocketを介してのみ作業する必要があります。 ここではすべてが明確です-これは私の省略です。なぜなら、
Unity Web Playerの下で極端なアプリケーションを作成したからです。これは通常の
Socketで動作します。
WebSocketで動作するようにネットワークを設定する問題を解決した後(これについては後で説明します)、次の問題に遭遇しました。 なぜなら 社会的 ネットワーク(少なくとも私が統合したネットワーク)は、セキュアなプロトコル(
Https )を介して機能し、そのコンテンツがセキュアなプロトコルを介して機能することも要求します。 「それは問題ではない」と思ったので、今からやろうと思った...数日間インターネットを「掘り」、
Unity開発者と話をして、私は憂鬱に
陥りました 。 私の知る限り、この場所のほとんどの開発者は「光子」に行きます。 しかし、私たちはそうではありません!
それで、社会は何をしますか。 ネットワーク。 通常のWebアセンブリの場合、通常の
WebSocketを使用して作業を楽しみます。
一般的なスクリプト
クライアント(c#):#if _CLIENT_ using UnityEngine; using UnityEngine.Networking; namespace EXAMPLE.CLIENT { public class NetworkClientExample : NetworkClient { NetworkWriter mWriter = new NetworkWriter(); public NetworkClientExample() : base() { Configure(NetworkableConfig.GetConnectionConfig(), 1); RegisterHandler(MsgType.Connect, OnConnect); RegisterHandler(MsgType.Disconnect, OnDisconnect); RegisterHandler(MsgType.Error, OnError); RegisterHandler((short)EnumRpc.RpcHelloWorld, RpcLobbbyHelloWorld); } public void OnConnect(NetworkMessage _msg) { Debug.Log("OnConnectLobby"); mWriter.StartMessage((short)EnumRpc.CmdHelloWorld); mWriter.Write("Hello from client"); mWriter.FinishMessage(); SendWriter(mWriter, Channels.DefaultReliable); } void OnDisconnect(NetworkMessage _msg) { Debug.Log("OnDisconnectLobby"); UnregisterHandler(MsgType.Connect); UnregisterHandler(MsgType.Disconnect); UnregisterHandler(MsgType.Error); UnregisterHandler((short)EnumRpc.RpcHelloWorld); } void OnError(NetworkMessage _msg) { Debug.Log("OnErrorLobby"); } void RpcLobbbyHelloWorld(NetworkMessage _msg) { Debug.Log(_msg.reader.ReadString()); } }
NetworkClientExampleを使用する(c#): NetworkClientExample client = new NetworkClientExample(); client.Connect(NetworkableConfig.ServerHost, NetworkableConfig.ServerPort);
クライアントとのサーバー接続(c#): #if _SERVER_ using UnityEngine; using UnityEngine.Networking; namespace EXAMPLE.SERVER { public class ConnectionServerExample: NetworkConnection { NetworkWriter mWriter = new NetworkWriter(); public void SendHelloWorld() { mWriter.StartMessage((short)EnumRpc.RpcHelloWorld); mWriter.Write("Hello from server"); mWriter.FinishMessage(); SendWriter(mWriter, Channels.DefaultReliable); } }
サーバー(c#): #if _SERVER_ using UnityEngine; using UnityEngine.Networking; namespace EXAMPLE.SERVER { public class NetworkServerExample : MonoBehaviour { public const int sMaxConnections = 5000; void Start() { NetworkServer.SetNetworkConnectionClass<ConnectionServerExample>(); ConnectionConfig config = NetworkableConfig.GetConnectionConfig(); NetworkServer.Configure(config, sMaxConnections); NetworkServer.RegisterHandler(MsgType.Connect, OnConnect); NetworkServer.RegisterHandler(MsgType.Disconnect, OnDisconnect); NetworkServer.RegisterHandler(MsgType.Error, OnError); NetworkServer.RegisterHandler((short)EnumRpc.CmdHelloWorld, CmdHelloWorld); NetworkServer.Listen(NetworkableConfig.ServerPort ); } void OnConnect(NetworkMessage _msg) { Debug.Log("OnConnect"); } void OnDisconnect(NetworkMessage _msg) { Debug.Log("OnDisconnect"); } public void OnError(NetworkMessage _msg) { Debug.Log("OnError"); } void CmdHelloWorld(NetworkMessage _msg) { Debug.Log(_msg.reader.ReadString()); ((ConnectionServerExample)_msg.conn).SendHelloWorld(); } } // class } // namespace #endif
ネットワーク定数(c#): using UnityEngine.Networking; namespace EXAMPLE { public enum EnumRpc : short { RpcHelloWorld = 1, CmdHelloWorld, } public static class NetworkableConfig {
WebSocketに行く
私の場合、サーバーゲームロジックは「モバイル」クライアントと「ブラウザ」クライアントの両方に共通する必要があるため、
WebSocketに切り替えることにしました。 しかし、後者の「スローダウン」について読んだ後、2台の並列サーバーを作成することにしました。 これらのサーバーの相互作用について考えていたときに、あるフォーラムで
NetworkServerSimpleクラスについて言及し、喜びました。 彼を
WebSocketに設定します。 そして、残りのことは、クライアントをコアサーバーに転送することだけです。
WebSocket用サーバー(c#): #if _SERVER_ using UnityEngine.Networking; namespace EXAMPLE.SERVER { class NetworkServerWebSocket : NetworkServerSimple { public void Start(ConnectionConfig _config, int _maxConnections) { base.Initialize(); base.Configure(_config, _maxConnections);
WebSocketサーバーを起動するには、メインサーバーのスクリプトを編集する必要があります。
NetworkServerExampleの修正(c#): public class NetworkServerExample : MonoBehaviour {
そして、それはすべてすぐに働きました...しかし、長くは続きませんでした。 両方のサーバーへの接続が同時に行われるまで。
Unetは 、すべての稼働中のサーバーの接続識別子の一意性という単純な問題を解決できないことが判明しました。 それは恥ずかしくて迷惑ですが、...松葉杖のないところです。 メインサーバーから可能な限り多くの接続をシフトすることで識別子を置き換える
WebSocket接続用のクラスを単に紹介します。 なぜなら サーバーはリモートであり、多くの場合専用です。接続に二重のリンク配列を割り当てるために、わずかなメモリの無駄で目を覆うことができます。 だから:
WebSocket接続サーバークラス(c#): #if _SERVER_ using UnityEngine.Networking; namespace EXAMPLE.SERVER { public class ConnectionLobbyServerWebSocket : NetworkConnection { public override void Initialize(string networkAddress, int networkHostId, int networkConnectionId, HostTopology hostTopology) { base.Initialize(networkAddress, networkHostId, networkConnectionId + NetworkServerExample.sMaxConnections, hostTopology); } public override bool TransportSend(byte[] bytes, int numBytes, int channelId, out byte error) { return NetworkTransport.Send(hostId, connectionId - NetworkServerExample.sMaxConnections, channelId, bytes, numBytes, out error); } }
今、すべてが大丈夫です!
保護されたWebSocket
なぜなら 私はサーバー管理の完全な素人です-私にとって、このアイテムは最も難しいことがわかりました。 ホスティングには、
Windows Serverを使用し
ます 。 そして、
IISの WSSから
WSへの転送のトピックに
取り組むほど、悪化しました。 確かに「Atts-Odmin」の場合、このタスクは簡単ですが、私は彼ではありません。 ただし、研究中
IISでは、 Apacheではこれが非常に簡単
であることに気付きました。 やった!
Apacheという言葉を知っています。 確かに、前述の管理者は
Windows Serverと Apacheの組み合わせから病気になるでしょう。
Apacheで
WSSから
WSに転送するには、その上で
SSLをサポートする必要があり(これについては実際の専門家から多くの情報があります)、モジュール「mod_proxy.so」および「mod_proxy_wstunnel.so」を有効にして転送を設定します。
httpd.conf
ここで、「my_proxy」は、クライアントへの接続に使用される識別子のいずれかです。 5500-
WebSocketサーバーをリッスンしているポート
WebSocketサーバーは既に目的のポートでリッスンしており、クライアント接続を構成するために残ります。
NetworkClientExampleの修正(c#) //... public NetworkClientExample() : base() { //... // . _VK_ - . #if _VK_ // - NetworkServer NetworkServer.useWebSockets = true; #endif //... } //...
NetworkClientExampleの使用(c#) NetworkClientExample client = new NetworkClientExample(); #if _VK_ client.Connect("_/my_proxy/", 443); #else client.Connect(NetworkableConfig.ServerHost, NetworkableConfig.ServerPort); #endif
your_domainは、プロトコルのないドメインの名前です。例:habrahabr.ru
my_proxyは、「httpd.conf」で指定したプロキシ識別子です
プロキシIDの後の「/」を忘れないでください!
残りはほとんどありません。 次に、通常のWebソケット(
WS )を介して
Unet要求を安全な
WSS Webソケットに
変換する必要があります。 これは、小さな
JavaScriptスクリプトを使用して、Webページの本文に直接挿入するか、プラグインとしてプロジェクトに接続することで実行できます。 2番目のオプションの方が快適でした。 したがって、プロジェクトの「Assets / Plugins」フォルダにスクリプトを作成します。たとえば、「WssHack.jspre」(拡張子「.jspre」、そうでない場合「little girl」は気まぐれです)と次の内容です。
WssHack.jspre(JavaScript) Object.defineProperty(Module, "asmLibraryArg", { set: function (value) { value._JS_UNETWebSockets_SocketCreate = function (hostId, urlPtr) { var url = Pointer_stringify(urlPtr).replace(/^ws:\/\//, "wss://"); urlPtr = Runtime.stackAlloc((url.length << 2) + 1); stringToUTF8(url, urlPtr, (url.length << 2) + 1); return _JS_UNETWebSockets_SocketCreate(hostId, urlPtr); }; Module._asmLibraryArg = value; }, get: function () { return Module._asmLibraryArg; }, });
すべてがあなたの役に立つことを願っています! ご質問、お気軽に。