Cafe capybara TECH-BLOG

PHPな会社でゴリゴリしてるあかいいぬの技術ブログです

TCP通信を確立して定期的に送受信を行うライブラリ作った

ゲームのリアルタイム通信用のTCPライブラリです。

半分自分用に仕様を書き残しておきます。

全体仕様

主に DataProtocolクラス, MyTcpClientクラス, MyTcpListenerクラス の三つで構成。

DataProtocolクラス

実際の通信データであるバイト配列をDataProtocolクラスによってラップし、通信用ヘッダーと基本型のコンテンツ(変換機能付)を付加して送受信可能にするクラス。

最初の数バイト(DataProtocol.HEADERSIZE)は通信用のヘッダーとして裏側で送受信されるデータ。

そのあとはListによる配列が続く。

  • byte Size - コンテンツのバイト数。
  • byte ContentId - 利用側が確認する、コンテンツ識別番号。
  • byte[] ContentBytes - 実際のコンテンツのバイト配列。

ContentData.GetContent(ContentDataType type) メソッドで実際のコンテンツのobjectを取得。

// 取得例
foreach (var content in data.ContentDatum)
  Console.Write((string)content.GetContent(ContentDataType.String));

これを使うことで使う側はバイト配列やIDの管理をしなくても通信データが確認できます。

MyTcpClientクラス

TcpClientクラスのラッパー。
これはサーバ側・クライアント側双方で使います。

通信接続・切断、DataProtocolデータ受信・送信を担当。

MyTcpListenerクラス

TcpListenerクラスのラッパー。
スレッドを生成して裏でデータの受信と新規接続の確認を行ってくれる。
SendData(byte remoteId, DataProtocol dp)メソッドを呼び出してデータを送信する



ここからは実際に使う時の流れ。

クライアント側

  1. MyTcpClient.Connect(string hostName, int port)メソッドで接続
  2. MyTcpClient.Availableがtrueの間バックグラウンドのスレッドで送受信ループ
    1. 送信:DataProtocolクラスを作成し初期化⇒MyTcpClient.SendData(DataProtocol dp)に渡して送信
    2. 受信:MyTcpClient.ReceiveData()メソッドでDataProtocolを受信してデータを処理
  3. 送受信時にエラーが出た際は自動で通信を終了し終了&明示的にMyTcpClient.Close()メソッドで終了可能

サーバ側

  1. MyTcpListenerを初期化してStart()
  2. 定期送信:MyTcpListener.SendingDataイベントで送信したいデータを別スレッドで処理
  3. 定期受信:MyTcpListener.ReceivingDataイベントで受信したデータを別スレッドで処理
  4. 新規接続:MyTcpListener.AddingClientイベントで新しい接続に関する処理
  5. 明示的に送信:MyTcpListener.SendData(DataProtocol dp)メソッドでデータ送信
  6. 送受信エラーかMyTcpListener.Stop()メソッドで終了



凄く簡単。
利用側は受信したDataProcotolのContentDataを、ContentIdを見ながら処理して送受信動作を行うだけです。

ゲームでの通信は大抵リアルタイム(秒間数~数十回)で送信と受信が繰り返されるので、メインスレッドとは別のスレッドを作ってそちらで送受信んを行うと思います。

サーバは別スレッドでのイベントがすでに用意されているので、そちらで定期的に送受信が可能。

クライアントもMyTcpClient.Connectに成功した際にスレッドが動き出しますので、イベントによる定期送受信ができます。

今はまだコンソール内でデバッグしているだけでまだゲームに適用していないので機能が足りないかもしれませんが、うまく動いてくれそうです。

今度は簡単な3D空間の移動と弾の処理、HP管理あたりを最低限実装したゲームにこのライブラリを導入して試してみます。

P.S. これだけ処理しても1,000行いかない小さいライブラリ