実際にアプリを作る過程で気づいたことメモとか。
そもそも通信の基本的な考えから微妙だった。
クライントからサーバへの通信と、サーバーからの一斉配信があれば組み合わせで行けるかと思っていた。
実際にはターン制ならサーバから特定クライアントへの配信は必須だし、サーバ機はクライアントにもなるので自分を含めて配信したい。
サーバは一意だからいいけどクライアントの識別ができない。
サーバスレッドへの接続通知にクライアントのMACアドレスを追加してUnity側で保存しておく。これでサーバは全クライアントの識別ができる。
サーバから特定のクライアントにメッセージを送りたい。
スレッドのメッセージ送信にアドレス指定できるものを追加。
1 2 3 4 |
protected void send(String msg,String addr) throws IOException { if(socket.getRemoteDevice().getAddress().equals(addr)) socket.getOutputStream().write((msg+"\n").getBytes()); } |
これをUnity側からアドレス指定で呼び出して全スレッドで実行する。
1 2 3 4 |
public void SendMessage(String msg,String addr) { try { for(ServerThread st : serverThreads){ st.send(msg,addr); } } catch (IOException e) { IOExpHandle(e); } } |
Unity(C#)を使ってると忘れがちだけど equals で比較する(ハマりポイント)。
サーバから自身を含めた全体に配信したい
ライブラリでどうこうするより、Unity側の送信メソッドから受け取り関数を直接呼び出す形でラップする。
サーバかクライアントかで挙動が変わるので isServer みたいなフラグが必要。
通信を切断したい
サーバ側から特定のクライアントをキックしたり、ゲーム終了時に全部切ったりする処理が欲しい。
サーバスレッドにクローズ処理を付ける。
1 2 3 4 5 6 7 8 9 10 11 |
private class ServerThread extends TransThread { private ServerThread(BluetoothSocket bs) { socket = bs; } public void run() { try {loop(true);} catch (IOException e) { IOExpHandle(e); } } private void close() { try { socket.close(); } catch (IOException e) { IOExpHandle(e); } } private void close(String addr) { try { if(socket.getRemoteDevice().getAddress().equals(addr))socket.close(); } catch (IOException e) { IOExpHandle(e); } } } |
クライアントから切断する処理はサンプルにあるので、そのまま使うとしてUnityから呼び出す関数を作る。
1 2 3 4 5 6 7 8 9 10 11 12 |
public void CloseConnectS2ALL() { try { for(ServerThread st : serverThreads){ st.send("CLOSE"); st.close(); } } catch (IOException e) { IOExpHandle(e); } } public void CloseConnectS2C(String addr) { try { for(ServerThread st : serverThreads){ st.send("CLOSE",addr); st.close(addr); } } catch (IOException e) { IOExpHandle(e); } } public void CloseConnectC2S(String msg,String addr) { try { if (clientThread != null){ clientThread.send("CLOSE"); clientThread.cancel(); } } catch (IOException e) { IOExpHandle(e); } } |
一応接続先にCLOSEを送っている。
接続管理はサーバでやった方が良さそうなのでC2Sは使わないかも。
その他
アプリ完成まで何かあり次第追記してく。