質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

1711閲覧

NIOを用いたTCPクライアントからのデータ送信が、呼び出すタイミングによって失敗してしまう。

inca1987

総合スコア20

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

1グッド

0クリップ

投稿2016/10/05 09:48

実装しようとしている流れ

  1. bluetoothの接続先デバイスをAndroid内で検出
  2. 接続先リストを一つづつAndroid上のUnityにTCPで送信

クラス

TCPClientForUnity : NIOを用いたTCPクライアントクラス
BTManager : Bluetoothの接続先を検出しUnityに送るクラス
ConnectionService : 上記2クラスを持つServiceクラス

問題・質問

下記のTCPClientForUnityが状況に依って動作しない場合があります。
TCPの送信は、TCPClientForUnityクラスのSendToUnity関数を呼んで行っているのですが、
・BTManagerクラスのStartConnect内から呼んだ場合動作せず、
・BTManagerクラスが持つBroadcastReceiverオブジェクト内から呼んだ場合動作します。

また、TCPクライアント↔サーバ間のソケットの接続が確立されたあとに、データを送信する関数を呼び出しているので、ソケットの通信自体には問題が無いものと思われます。

大変混みあった状況で申し訳ないのですが、このような状況では何の原因を疑うべきか、誤りは何か等ご教授いただけると幸いです。

TCPClientForUnity

Java

1public class TCPClientForUnity{ 2 3 private SocketChannel mSocketChannel; 4 private Selector mSelector; 5 private static int mBufferLength = 1024; 6 private ByteBuffer mWriteBuffer; 7 private ByteBuffer mReadBuffer; 8 private String mAddress; 9 private int mPort; 10 11 public TCPClientForUnity(final String adr, final int PORT){ 12 mAddress = adr; 13 mPort = PORT; 14 mWriteBuffer = ByteBuffer.allocate(mBufferLength); 15 mReadBuffer = ByteBuffer.allocate(mBufferLength); 16 } 17 18 public void CreateSocketChannel(final String adr, final int PORT){ 19 try { 20 mSelector = Selector.open(); 21 mSocketChannel = SocketChannel.open(); 22 mSocketChannel.configureBlocking(false); 23 mSocketChannel.connect(new InetSocketAddress(adr, PORT)); 24 mSocketChannel.register(mSelector, SelectionKey.OP_CONNECT); 25 }catch(IOException e){ 26 e.printStackTrace(); 27 } 28 } 29 30 private final Runnable mAcceptTask = new Runnable() { 31 public void run() { 32 System.out.println("start runnnable"); 33 34 try { //IOException 35 36 //while (!Thread.interrupted()) { // try to connect 37 while (true) { // try to connect 38 try { //ConnectException 39 40 CreateSocketChannel(mAddress, mPort); 41 System.out.println("connect loop ater mSelector.select()"); 42 System.out.println("!Thread.interrupted(): " + !Thread.interrupted() + " mSocketChannel.isOpen(): " + mSocketChannel.isOpen()); 43 //while (!Thread.interrupted() & mSocketChannel.isOpen() & mSelector.select()>0) { 44 while (mSocketChannel.isOpen()) { 45 int select_len = mSelector.selectNow(); 46 //System.out.println("select length: " + select_len); 47 if (select_len > 0){ 48 //System.out.println("select loop"); 49 Iterator<SelectionKey> keys = mSelector.selectedKeys().iterator(); 50 51 while (keys.hasNext()) { 52 //System.out.println("keys.hasNext"); 53 SelectionKey key = keys.next(); 54 keys.remove(); 55 56 if (key.isConnectable()) { 57 System.out.println("connecting..."); 58 mSocketChannel.finishConnect(); // if connection fail, throw ConnectException 59 System.out.println("CLIENT: Connected"); 60 mSocketChannel.register(mSelector, SelectionKey.OP_READ, mReadBuffer); 61 } 62 63 if (key.isWritable()) { 64 System.out.println("is writable"); 65 if (mWriteBuffer.hasRemaining()) { 66 mSocketChannel.write(mWriteBuffer); 67 System.out.println("CLIENT: Write " + ByteBuffer2String(mWriteBuffer)); 68 mWriteBuffer.clear(); 69 } 70 mSocketChannel.register(mSelector, SelectionKey.OP_READ, mReadBuffer); 71 } 72 73 if (key.isReadable()) { 74 System.out.println("is readable"); 75 ByteBuffer readBuf = (ByteBuffer) key.attachment(); 76 if (readBuf.hasRemaining()) { 77 mSocketChannel.read(readBuf); 78 String msg = ByteBuffer2String(readBuf); 79 System.out.println("CLIENT: Read " + msg); 80 ClassifyMsg(msg); 81 readBuf.clear(); 82 } 83 mSocketChannel.register(mSelector, SelectionKey.OP_READ, readBuf); 84 //mSocketChannel.close(); 85 //break loop; 86 } 87 } 88 } 89 } 90 } catch (ConnectException e) { 91 e.getStackTrace(); 92 try{ 93 Thread.sleep(100); 94 }catch (InterruptedException e2){ 95 e2.getStackTrace(); 96 } 97 } 98 } 99 }catch (IOException e) { 100 e.getStackTrace(); 101 } 102 } 103 }; 104 105 106 public void SendToUnity(String msg){ 107 msg += "\n"; 108 System.out.println("in TCPClientForUnity, msg: " + msg); 109 mWriteBuffer.clear(); 110 mWriteBuffer.put(msg.getBytes(Charset.forName("UTF-8"))); 111 mWriteBuffer.flip(); 112 113 try{ 114 mSocketChannel.register(mSelector, SelectionKey.OP_WRITE); 115 }catch (IOException e){ 116 e.getStackTrace(); 117 } 118 } 119}

BTManager

文字数不足のため外部サイトへ

ConnectionService

外部サイト

GeeChiki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決致しました。
原因はTCPClientForUnityの条件、if(key.isReadable())のデータ受信時の読み込み待ち状態に遷移するレジスタ設定のタイミングにありました。

ClassifyMsg(msg)→…→SendToUnity(String msg)で書き込み待ち状態に遷移するレジスタ設定mSocketChannel.register(mSelector, SelectionKey.OP_WRITE)を行ってすぐ、読み込み待ち状態に遷移するレジスタ設定mSocketChannel.register(mSelector, SelectionKey.OP_READ, readBuf);を行ってしまっていたため、

ClassifyMsg(msg)→…→SendToUnity(String msg)間のディレイが極端に少ない場合に、「書き込み待ち状態に遷移しない」という問題が発生していたようです。

上記問題を解消したコードを示します。

Java

1if (key.isReadable()) { 2 ByteBuffer readBuf = (ByteBuffer) key.attachment(); 3 if (readBuf.hasRemaining()) { 4 mSocketChannel.read(readBuf); 5 String msg = ByteBuffer2String(readBuf); 6 readBuf.clear(); 7 mSocketChannel.register(mSelector, SelectionKey.OP_READ, readBuf); 8 ClassifyMsg(msg); 9 }else{ 10 mSocketChannel.register(mSelector, SelectionKey.OP_READ, readBuf); 11 } 12}

自分でも混乱したまま質問を投げた所為か、伝わらない質問になってしまった事をお詫びいたします。
ありがとうございます。

投稿2016/10/07 01:43

inca1987

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問