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

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

ただいまの
回答率

87.78%

pcをサーバーとし、androidをクライアントとしたソケット通信を行いたい。

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,409

score 13

 前提・実現したいこと

pcをサーバーとし、androidをクライアントとしたソケット通信を行いたい。

 発生している問題・エラーメッセージ

pcでサーバーのプログラムを起動し待ち状態にした後に、クライアントとしたandroid studioを実行しているが、サーバー側で受信出来ないでいます。
内容としてはandroid studioでボタンを押すことで文字列を送った際に、サーバー側で偶数か奇数か判別するものになっており、今はクライアント側で「2」を送信しています。eclipseもandroid studioもエラーははかず実行できている状態です。
android studioではインターネット接続を行うパーミッションは追加してあります。
エラーが出ないためなぜサーバー側で受信できていないのか、もしくはクライアント側が送信できていないのか教えて頂けないでしょうか。よろしくお願い致します。
ソースコードは以下になります。

 該当のソースコード

//クライアント側
import android.app.Activity;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

class SocketConnection extends Activity {

    void Connect(){

        Socket cSocket = null;
        PrintWriter writer = null;
        BufferedReader reader = null;

        try{
            cSocket = new Socket(IPアドレス, ポート番号);

            //送信
            writer = new PrintWriter
                    (cSocket.getOutputStream(), true);

            //受診
            reader = new BufferedReader
                    (new InputStreamReader
                            (cSocket.getInputStream()));

            while (true) {
                writer.println("2");

                Log.d("test","サーバー側回答:" + reader.readLine());
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) {
                    writer.close();
                }
                if (cSocket != null) {
                    cSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("終了");
        }
    }
}

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button b1=findViewById(R.id.button);
        b1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                SocketConnection s = new SocketConnection();
                s.Connect();
            }
        });
    }
}
//サーバー側
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

class Socket_Connection {


    void connect() throws Exception {

        ServerSocket sSocket = null;
        Socket socket = null;
        BufferedReader reader = null;
        PrintWriter writer = null;

        try{
            //ソケットを作成
            sSocket = new ServerSocket();
            sSocket.bind(new InetSocketAddress
                    (IPアドレス,ポート番号));

            System.out.println("入力待ち");

            socket = sSocket.accept();

            //受信
            reader = new BufferedReader(
                    new InputStreamReader
                    (socket.getInputStream()));

            //送信
            writer = new PrintWriter(
                    socket.getOutputStream(), true);

            String line = null;
            int num;
            while (true) {

                line = reader.readLine();

                try{
                    num = Integer.parseInt(line);

                    if(num%2==0){
                        writer.println("OK");                
                    }else{
                        writer.println("NG");
                    }
                }catch(NumberFormatException e){
                    writer.println("偶数を入力して下さい");
                }
                System.out.println("文字列=" + line);
            }            
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if (reader!=null){
                    reader.close();
                }
                if (writer!=null){
                    writer.close();
                }
                if (socket!=null){
                    socket.close();
                }
                if (sSocket!=null){
                    sSocket.close();
                }
                System.out.println("サーバー側終了です");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args) throws Exception{
        Socket_Connection sc =new Socket_Connection();
        sc.connect();
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • euledge

    2018/11/15 23:06

    サーバーとAndroid Studioは同じPCで動いていませんよね? 同じポート番号では片方のソケット開けなくなります。

    キャンセル

  • wanwanteikoku

    2018/11/15 23:21

    別のPCでおこなっております。

    キャンセル

  • euledge

    2018/11/15 23:30

    WireSharkなどのパケット解析ツールで送受信されている様子を確認すると解決が早いかもです。

    キャンセル

回答 2

0

まずは、クライアントからサーバにpingがとおるかやってみることですね

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

コードに改めるべき点がいくらか見られますが、私が開発環境を動かせる状況にないため、細かいことを記すことができません。少し待っていただければ、検証したコードの例示付きで回答します。


遅くなりましたが、回答の詳細です。

まずサーバー側ですが、「ソケットを作成」というコメントの部分で、bind()の引数にIPアドレスを与えると接続を受け付けるネットワークを指定することになります。どこからでも受け付けるサーバーを作る場合、通常はポート番号を指定するだけです。ですから、

            //ソケットを作成
            sSocket = new ServerSocket();
            sSocket.bind(new InetSocketAddress(ポート番号));


のようにしましょう。

それから連続で待ち受けるように繰り返す区間ですが、この繰り返し方では正しく動作しないと思います。

            while (true) {
                socket = sSocket.accept();


のように、繰り返し開始をaccept()の前に持ってくるべきでしょう。

次にクライアント側ですが、前回のご質問での私の回答に誤りがあって、Android 3.0以降ではUIスレッド上でネットワーク接続を行うとNetworkOnMainThreadExceptionという例外が飛んで正常に動作しないという問題がありました。ですから、リンクを示したサンプルは現在のAndroid SDKでは動きません。大変申し訳ありませんでした。

正しく動くようにするには、その回答の末尾に書いた通りThreadやAsyncTaskといった別スレッド実装が必要です。記していただいたコードから修正するには、SocketConnectionクラスは

class SocketConnection extends AsyncTask {
    @Override
    protected Void doInBackground(Void... voids) {
        Connect();
        return null;
    }

    void Connect(){
        // ここは現状通り
    }
}

のようにAsyncTaskを継承するように改めて、これを呼び出すMainActivityでは

            public void onClick(View view) {
                SocketConnection s = new SocketConnection();
                s.execute();
            }


のようにすれば、SocketConnectionに記述したConnect()を非同期タスクとして動かすことができるでしょう。

また、Connect()の中でwhile文による永久ループを作っていますが、スレッドを永久に回す設計では正しく動作しません。このwhile文は除去して、一度のConnect()実行で一つのメッセージのやり取りのみを行う方向にしましょう。

            //while (true) {
                writer.println("2");

                Log.d("test","サーバー側回答:" + reader.readLine());
            //}

これだけ改修すれば、ボタンを1度押せば一つのメッセージの送受信を行えるようになるのではないかと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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