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

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

ただいまの
回答率

88.21%

socket通信による画像の複数回送信(android)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,110

Mustard

score 11

socketで画像を転送するプログラムを作成しています。
以前の質問にて実装できたと思っていたのですが、一度きりの送受信しかできないことが発覚しました。複数回送受信するにはどうすればよいのでしょうか...以下に作成したプログラムの一部を示します。

public class ChatManager implements Runnable{
    private Socket socket = null;
    private Handler handler;
    byte[] pvbyte = null;//受信したプレビュー画像

    public ChatManager(Socket socket, Handler handler) {
        this.socket = socket;
        this.handler = handler;
    }

    private InputStream iStream;
    private OutputStream oStream;
    ByteArrayOutputStream bospv;
    InputStream is;
    private static final String TAG = "ChatHandler";

    @Override
    public void run() {
        try {

            iStream = socket.getInputStream();
            oStream = socket.getOutputStream();

            handler.obtainMessage(WiFiServiceDiscoveryActivity.MY_HANDLE, this).sendToTarget();

            bospv = new ByteArrayOutputStream();
            copyFile(iStream, bospv);//受信データをbospvにコピー
            pvbyte = bospv.toByteArray();
            handler.obtainMessage(WiFiServiceDiscoveryActivity.MESSAGE_READ, pvbyte).sendToTarget();//結果をアクティビティへ

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void write(byte[] buffer) {
        is =  new ByteArrayInputStream(buffer);
        copyFile(is,oStream);
    }
    public static boolean copyFile(InputStream inputStream, OutputStream out) {
        byte buf[] = new byte[1024];
        int len;
        try {
            while ((len = inputStream.read(buf)) != -1) {
                out.write(buf, 0, len);

            }
            out.flush();
            out.close();
           inputStream.close();
        } catch (IOException e) {
            Log.d("debug", e.toString());
            return false;
        }
        return true;
    }
}


また、参考にした公式サンプルのソースは下記の通りです。

public class ChatManager implements Runnable {

    private Socket socket = null;
    private Handler handler;

    public ChatManager(Socket socket, Handler handler) {
        this.socket = socket;
        this.handler = handler;
    }

    private InputStream iStream;
    private OutputStream oStream;
    private static final String TAG = "ChatHandler";

    @Override
    public void run() {
        try {

            iStream = socket.getInputStream();
            oStream = socket.getOutputStream();
            byte[] buffer = new byte[1024];
            int bytes;
            handler.obtainMessage(WiFiServiceDiscoveryActivity.MY_HANDLE, this)
                    .sendToTarget();

            while (true) {
                try {
                    // Read from the InputStream
                    bytes = iStream.read(buffer);
                    if (bytes == -1) {
                        break;
                    }

                    // Send the obtained bytes to the UI Activity
                    Log.d(TAG, "Rec:" + String.valueOf(buffer));
                    handler.obtainMessage(WiFiServiceDiscoveryActivity.MESSAGE_READ,
                            bytes, -1, buffer).sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void write(byte[] buffer) {
        try {
            oStream.write(buffer);
        } catch (IOException e) {
            Log.e(TAG, "Exception during write", e);
        }
    }

}


原因はもともとのプログラムではwhile(true)で無限ループとなっていた受信待ち部分が書き換えたことにより消えてしまったことだと思うのですが、

whle(true){
 copyFile(iStream, bospv);//受信データをbospvにコピー
 pvbyte = bospv.toByteArray();
 handler.obtainMessage(WiFiServiceDiscoveryActivity.MESSAGE_READ, pvbyte).sendToTarget();//結果をアクティビティへ
}


とすると同じ画像を無限に取得し続けすぐにアプリが落ちます。また、

 while (true) {
                try {
                    // Read from the InputStream
                    bytes = iStream.read(buffer);
                    if (bytes == -1) {
                        Log.d(TAG, "loop end");
                        break;
                    }
                    bospv.write(buffer,0,bytes);
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                }
            }
            pvbyte=bospv.toByteArray();
            handler.obtainMessage(WiFiServiceDiscoveryActivity.MESSAGE_READ, pvbyte).sendToTarget();


とするとbytesが-1になることがなくいつまでもobtainMessageが呼ばれません。
修正方法や構造の間違いなどご指摘お願いいたします。

(追記)
1回は送信できることを確認しているためsocket.close()後にまた新たにsocketやChatManagerを作成することで対応できないかと考えたのですがどうでしょうか。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • keicha_hrs

    2019/05/10 23:00

    Socket.IOタグはこの質問には関係ないので外しましょう。

    キャンセル

回答 1

checkベストアンサー

0

Streamと名のつくものは、一連なりのデータと考えましょう。
順番にデータを読み込み、あるいは、順番にデータを書き込みます

順番にデータを読み込んでいって、データが尽きると、そこからはデータが読めなくなります
も一度最初からデータを読みたい場合は、
・ファイル位置のポインタを最初に設定し直す
・そのStreamを作成し直す
のいずれかの操作を行う必要があります

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/11 17:05

    おっしゃる通りでした。
    socket.close後にクライアント側が
    nHandler =new ClientSocketHandler(this.handler,groupOwnerAddress);
    nHandler.start();
    を呼び出すことで解決いたしました。
    迅速な回答にお礼申し上げます。

    キャンセル

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

  • ただいまの回答率 88.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る