現在、ラズパイをサーバー(Java)としてローカルでUnity同士でチャットする機能を開発しようとしております。
まず、以下のコードでUnityからメッセージをラズパイへ向けて送信し、ラズパイからもUnityへ送信する事はできました。
その後、Java側のコードをUnity側から受信があれば今まで接続があったIPアドレスに対してブロードキャストするためのsendメソッド、C#側のコードにはTcpListenerとブロードキャストされたデータを受信するためのListenerメソッドを追加し、送信してすぐ受信する処理を削除しました。
Java
1import java.io.DataInputStream; 2import java.io.DataOutputStream; 3import java.io.IOException; 4import java.io.InputStream; 5import java.net.ServerSocket; 6import java.net.Socket; 7import java.text.SimpleDateFormat; 8import java.util.ArrayList; 9import java.util.Date; 10 11/** 12 * ラズパイ上で動かすチャットのサーバークラスです 13 * @author reishisu 14 */ 15public class ChatServer { 16 17 /** 18 * ソケット通信を行うポート 19 */ 20 public static final int PORT = 25252; 21 /** 22 * チャットサーバーの窓口 23 */ 24 private static ServerSocket server_socket; 25 /** 26 * 接続してきたIPアドレス 27 */ 28 private static ArrayList<String> client_list = new ArrayList<>(); 29 30 /** 31 * メイン関数 32 * @param args コマンドライン引数 33 */ 34 public static void main(String[] args) { 35 try { 36 // 既にサーバーが建っていない時サーバーソケットの生成 37 if (server_socket == null) { 38 server_socket = new ServerSocket(PORT); 39 System.out.println("サーバー稼働中..."); 40 } 41 42 // 受信カウンタ 43 int count = 1; 44 45 // サーバー稼働 46 while (true) { 47 // クライアントからの接続が来るまで待機 48 Socket client_socket = server_socket.accept(); 49 50 // 新規か確認 51 boolean is_new = true; 52 for(String ip : client_list) { 53 if (ip == client_socket.getInetAddress().toString()) { 54 is_new = false; 55 } 56 } 57 if (is_new) client_list.add(client_socket.getInetAddress().toString()); 58 59 // 計測開始 60 long start_time = System.currentTimeMillis(); 61 62 // クライアントから文字列をバイト列で受信 63 InputStream input_stream = client_socket.getInputStream(); 64 DataInputStream data_input_stream = new DataInputStream(input_stream); 65 66 // 文字列を受け取るバッファー 67 byte[] buffer = new byte[4096]; 68 int byte_count = 0; 69 String message = ""; 70 try { 71 byte_count = data_input_stream.read(buffer); 72 if (byte_count == 0) return; 73 String view_string = new String(buffer, "UTF-8"); 74 long end_time = System.currentTimeMillis(); 75 SimpleDateFormat time_stamp = new SimpleDateFormat("yyyy年MM月dd日HH時mm分ss秒"); 76 message += count + " IPアドレス:" + ("" + client_socket.getInetAddress()).split("/")[1] + ":" + 77 time_stamp.format(new Date()) + " [" + (end_time - start_time) + "ms]" + "\n" + view_string + "\n"; 78 System.out.println(message); 79 count++; 80 81 send(message, client_socket.getInetAddress().toString()); 82 } 83 catch (Exception e) { 84 long end_time = System.currentTimeMillis(); 85 SimpleDateFormat time_stamp = new SimpleDateFormat("yyyy年MM月dd日HH時mm分ss秒"); 86 message += count + " IPアドレス:" + ("" + client_socket.getInetAddress()).split("/")[1] + ":" + 87 time_stamp.format(new Date()) + " [" + (end_time - start_time) + "ms]" + "\n受信失敗...\n"; 88 System.out.println(message); 89 count++; 90 91 send(message, client_socket.getInetAddress().toString()); 92 } 93 } 94 } 95 catch (Exception e) { 96 System.err.println("エラー発生!!"); 97 e.printStackTrace(); 98 } 99 } 100 101 public static void send(String message, String now_ip) { 102 byte[] buffer = new byte[4096]; 103 DataOutputStream dataOutputStream = null; 104 try { 105 buffer = message.getBytes("UTF-8"); 106 107 for (String ip : client_list) { 108 if (ip == now_ip) continue; 109 dataOutputStream = new DataOutputStream(new Socket(ip.split("/")[1], PORT).getOutputStream()); 110 dataOutputStream.write(buffer); 111 dataOutputStream.flush(); 112 } 113 dataOutputStream.close(); 114 115 } catch (IOException e) { 116 // TODO 自動生成された catch ブロック 117 e.printStackTrace(); 118 } 119 } 120}
C#
1using System.Collections; 2using System.Collections.Generic; 3using System; 4using UnityEngine; 5using UnityEngine.UI; 6using System.Net.Sockets; 7using System.Text; 8using System.Net; 9using System.Threading.Tasks; 10 11public class ChatClient : MonoBehaviour { 12 13 // ゲームオブジェクト 14 public InputField input_field; 15 public GameObject content; 16 public GameObject chat_log; 17 18 // サーバー情報 19 private string server_ip_address = "192.168.0.25"; 20 private int port = 25252; 21 22 // クライアントの送信窓口 23 NetworkStream network_stream; 24 25 // 送信内容 26 private string send_text; 27 28 // 受信用 29 private TcpListener listener; 30 private float request_span = 10f; 31 private byte[] buffer = new byte[4096]; 32 33 34 // Start is called before the first frame update 35 void Start() { 36 37 network_stream = new TcpClient(server_ip_address, port).GetStream(); 38 Debug.Log(network_stream.Read(buffer, 0, buffer.Length)); 39 network_stream.Close(); 40 41 //Componentを扱えるようにする 42 input_field = input_field.GetComponent<InputField>(); 43 // 受信用 44 listener = new TcpListener(IPAddress.Parse(server_ip_address), port); 45 46 Task.Run(Listener); 47 } 48 49 public void InputText() { 50 //テキストにinputFieldの内容を反映 51 send_text = input_field.text; 52 } 53 54 // ボタンクリック時 55 public void NetworkRequest() { 56 // 接続要求 57 network_stream = new TcpClient(server_ip_address, port).GetStream(); 58 59 // 送信の内容をセット 60 if (send_text.Length == 0) return; 61 byte[] send_string = Encoding.UTF8.GetBytes(send_text); 62 63 // データを送信 64 network_stream.Write(send_string, 0, send_string.Length); 65 66 network_stream.Close(); 67 } 68 69 70 public void Listener() { 71 listener = new TcpListener(IPAddress.Parse(server_ip_address), port); 72 Debug.Log("監視開始1"); 73 74 listener.Start(); 75 Debug.Log("監視開始2"); 76 while (true) { 77 //接続要求があったら受け入れる 78 TcpClient client = listener.AcceptTcpClient(); 79 80 Debug.Log("きた!"); 81 82 // データを受信 83 network_stream.Read(buffer, 0, buffer.Length); 84 string message = Encoding.UTF8.GetString(buffer); 85 GameObject instance = Instantiate(chat_log); 86 instance.transform.parent = content.transform; 87 instance.transform.localScale = new Vector3(1, 1, 1); 88 instance.GetComponent<Text>().text = message; 89 90 // バッファリセット 91 buffer = new byte[4096]; 92 } 93 } 94 95} 96
そして、修正したコード動かしてみるとUnityから送信まではできたのですが、Javaからブロードキャストする際に以下のエラーメッセージが出てきて送信が出来ず、Unity側でも勿論反応がありません。
また、Unity側では起動時に"監視開始1"は表示されているのですが、その後"監視開始2"は表示されません。
サーバー稼働中... 1 IPアドレス:192.168.0.5:2019年07月09日03時13分43秒 [6ms] [壁]*´・ω・`)ノ コンニチハ.:゚+ java.net.ConnectException: 接続を拒否されました at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at java.net.Socket.<init>(Socket.java:434) at java.net.Socket.<init>(Socket.java:211) at ChatServer.send(ChatServer.java:109) at ChatServer.main(ChatServer.java:81)
色々調べてみましたが原因がわからず困っております...
あまりネットワークの通信に詳しくないのでわかる方がいらっしゃいましたら、どうかご教授いただきたいです。
補足情報(FW/ツールのバージョンなど)
ー 開発環境 ー
MacBook Pro (15-inch, 2016)
OS : macOS mojave
バージョン : Unity 2018.2.2f1
IPアドレス : 192.168.0.5
Raspberry Pi 3 Model B+
OS : Raspbian GNU/Linux 9
バージョン : Java SE 8
IPアドレス : 192.168.0.25
追記
Unity側で全くエラーが出てなかったので心配していなかったのですが、回答して頂いた内容を元にlistener.Start()にtry-catchを入れてみるとまさかのエラーが表示されておりました。。。
エラーを確認したばかりなので、今から原因を調べてみますが取り急ぎ追記させていただきました。
e.Messageの結果
The requested address is not valid in this context UnityEngine.Debug:Log(Object) ChatClient:Listener() (at Assets/Scripts/ChatClient.cs:80) System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
e.TargetSiteの結果
Void Bind(System.Net.EndPoint) UnityEngine.Debug:Log(Object) ChatClient:Listener() (at Assets/Scripts/ChatClient.cs:81) System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
e.StackTraceの結果
at System.Net.Sockets.Socket.Bind (System.Net.EndPoint localEP) [0x00043] in <3845a180c26b4889bc2d47593a665814>:0 at System.Net.Sockets.TcpListener.Start (System.Int32 backlog) [0x00044] in <3845a180c26b4889bc2d47593a665814>:0 at System.Net.Sockets.TcpListener.Start () [0x00000] in <3845a180c26b4889bc2d47593a665814>:0 at ChatClient.Listener () [0x00029] in /Users/reishisu/Documents/Unity/SocketTest/Assets/Scripts/ChatClient.cs:78 UnityEngine.Debug:Log(Object) ChatClient:Listener() (at Assets/Scripts/ChatClient.cs:80) System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/08 20:00
2019/07/09 00:31
2019/07/09 10:37
2019/07/09 13:00
2019/07/09 13:06
2019/07/09 13:18
2019/07/09 13:28
2019/07/09 13:35
2019/07/09 13:54