Android端末同士でSocketとDatagramSocketを使用する

##環境
- Windows 7
- AndroidStudio 3.0

##SocketとDatagramSocketの違い
SocketはTCP/IP通信。DatagramSocketはUDP/IP通信。

サンプルのプロジェクトをgithubにあげてみた。
https://github.com/sourcekatu/Android_Sample

##使い方
それぞれの端末にClientとServerを入れれば使える。

![Screenshot_2018-06-09-23-10-29.png](https://qiita-image-store.s3.amazonaws.com/0/256346/98a52524-75c7-ba9f-49da-1212fca41267.png)

![Screenshot_2018-06-09-23-09-14.png](https://qiita-image-store.s3.amazonaws.com/0/256346/7e15d0d1-2a63-8917-1139-f50df242016e.png)

##ソースコード
全てのプロジェクトにpermissionを追加する必要あり。↓のように
uses-permission android:name="android.permission.INTERNET"
が必要。
![WS000022.JPG](https://qiita-image-store.s3.amazonaws.com/0/256346/45ccd4b8-4ae9-2d62-1229-226680e0a246.jpeg)



ソースコードは以下のとおり。

```java:Sample_Socket_Client.java
public class MainActivity extends AppCompatActivity {
![WS000022.JPG](https://qiita-image-store.s3.amazonaws.com/0/256346/cc9f769a-30d5-60cf-3a48-8025239288a1.jpeg)

    Spinner spinner1;   // IPアドレス1
    Spinner spinner2;   // IPアドレス2
    Spinner spinner3;   // IPアドレス3
    Spinner spinner4;   // IPアドレス4
    EditText et;         // 送信テキスト

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

        spinner1 = (Spinner) findViewById(R.id.spinner);
        spinner2 = (Spinner) findViewById(R.id.spinner2);
        spinner3 = (Spinner) findViewById(R.id.spinner3);
        spinner4 = (Spinner) findViewById(R.id.spinner4);

        // IPアドレス設定 0 ～ 255 Start-----------------------------------
        String items[] = new String[256];
        int ii;

        for (ii = 0; ii < 256; ii++)
        {
            items[ii] = String.valueOf(ii);
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, items);

        spinner1.setAdapter(adapter);
        spinner2.setAdapter(adapter);
        spinner3.setAdapter(adapter);
        spinner4.setAdapter(adapter);
        // IPアドレス設定 0 ～ 255 End------------------------------------

        // IPアドレスの初期値設定 192.168.0.0
        spinner1.setSelection(192);
        spinner2.setSelection(168);
        spinner3.setSelection(0);
        spinner4.setSelection(0);

        Button button = (Button) findViewById(R.id.button);

        // 送信ボタン押下処理
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String IPAddress = String.valueOf(spinner1.getSelectedItem()) + '.' +
                                   String.valueOf(spinner2.getSelectedItem()) + '.' +
                                   String.valueOf(spinner3.getSelectedItem()) + '.' +
                                   String.valueOf(spinner4.getSelectedItem());

                et = (EditText)findViewById(R.id.editText);
                byte buf[] = new byte[et.length()];

                // データの送信はbyte配列方になるので変換
                for (int ii = 0; ii < et.length(); ii++ )
                {
                    buf[ii] = (byte) et.getText().charAt(ii);
                }

                // ソケット通信用にポート設定。送信したいデータとIPアドレス設定。
                InetSocketAddress inetSocketAddress = new InetSocketAddress(IPAddress, 5000);

                // Androidではソケット通信は別スレッドにする必要がある。ここで非同期通信。
                AsyncTask<InetSocketAddress, Void, Void> task = new AsyncTask<InetSocketAddress, Void, Void>() {
                    @Override
                    protected Void doInBackground(InetSocketAddress... inetSocketAddresses) {
                        Socket socket = null;
                        try {
                            // 接続
                            socket = new Socket();
                            socket.connect(inetSocketAddresses[0]);

                            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

                            // データを送信。
                            writer.write(et.getText().toString());

                            // クローズしておかないと、受信側でデータが反映されなかった。多分、クローズしたときに受信が側にデータが反映される。
                            writer.close();

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

                        return null;
                    }
                };
                task.execute(inetSocketAddress);
            }
        });
    }
}
```

```java:Sample_Socket_Server.java
public class MainActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final EditText et;
                et = (EditText)findViewById(R.id.editText);

                AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {

                    @Override
                    protected String doInBackground(Void... voids) {

                        // データ受信準備
                        String receiveString = "NG";
                        ServerSocket serverSocket = null;
                        BufferedReader reader = null;

                        // データ受信
                        try {
                            serverSocket = new ServerSocket(5000);

                            // ここでデータを受信するまで待機
                            Socket socket = serverSocket.accept();

                            // 受信したデータを格納
                            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                            receiveString = reader.readLine();

                            reader.close();
                            socket.close();
                            serverSocket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return receiveString;
                    }

                    @Override
                    protected void onPostExecute(String string) {

                        // 受信したデータを表示。
                        et.setText(string);
                    }
                };
                task.execute();
            }
        });
    }
}
```

```java:Sample_Datagram_Socket_Client.java
public class MainActivity extends AppCompatActivity {

    Spinner spinner1;   // IPアドレス1
    Spinner spinner2;   // IPアドレス2
    Spinner spinner3;   // IPアドレス3
    Spinner spinner4;   // IPアドレス4
    EditText et;         // 送信テキスト

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

        spinner1 = (Spinner) findViewById(R.id.spinner);
        spinner2 = (Spinner) findViewById(R.id.spinner2);
        spinner3 = (Spinner) findViewById(R.id.spinner3);
        spinner4 = (Spinner) findViewById(R.id.spinner4);

        // IPアドレス設定 0 ～ 255 Start-----------------------------------
        String items[] = new String[256];
        int ii;

        for (ii = 0; ii < 256; ii++)
        {
            items[ii] = String.valueOf(ii);
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, items);

        spinner1.setAdapter(adapter);
        spinner2.setAdapter(adapter);
        spinner3.setAdapter(adapter);
        spinner4.setAdapter(adapter);
        // IPアドレス設定 0 ～ 255 End------------------------------------

        // IPアドレスの初期値設定 192.168.0.0
        spinner1.setSelection(192);
        spinner2.setSelection(168);
        spinner3.setSelection(0);
        spinner4.setSelection(0);

        Button button = (Button) findViewById(R.id.button);

        // 送信ボタン押下処理
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String IPAddress = String.valueOf(spinner1.getSelectedItem()) + '.' +
                                   String.valueOf(spinner2.getSelectedItem()) + '.' +
                                   String.valueOf(spinner3.getSelectedItem()) + '.' +
                                   String.valueOf(spinner4.getSelectedItem());

                et = (EditText)findViewById(R.id.editText);
                byte buf[] = new byte[et.length()];

                String string = et.getText().toString();

                // 日本語を通信できるようにする。
                try {
                    buf = string.getBytes("SHIFT_JIS");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                // ソケット通信用にポート設定。送信したいデータとIPアドレス設定。
                InetSocketAddress inetSocketAddress = new InetSocketAddress(IPAddress, 5000);
                DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, inetSocketAddress);

                // Androidではソケット通信は別スレッドにする必要がある。ここで非同期通信。
                AsyncTask<DatagramPacket, Void, Void> task = new AsyncTask<DatagramPacket, Void, Void>() {
                    @Override
                    protected Void doInBackground(DatagramPacket... datagramPackets) {
                        DatagramSocket datagramSocket = null;
                        try {
                            datagramSocket = new DatagramSocket();
                            datagramSocket.send(datagramPackets[0]);
                            datagramSocket.close();
                        } catch (SocketException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        return null;
                    }
                };
                task.execute(datagramPacket);
            }
        });
    }
}
```

```java:Sample_Datagram_Socket_Server.java
public class MainActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final EditText et;
                et = (EditText)findViewById(R.id.editText);

                AsyncTask<Void, Void, DatagramPacket> task = new AsyncTask<Void, Void, DatagramPacket>() {

                    @Override
                    protected DatagramPacket doInBackground(Void... voids) {

                        // データ受信準備
                        byte receiveBuff[] = new byte[1000];
                        DatagramSocket datagramSocket = null;
                        DatagramPacket datagramPacket = new DatagramPacket(receiveBuff, receiveBuff.length);

                        // データ受信
                        try {
                            datagramSocket = new DatagramSocket(5000);
                            datagramSocket.receive(datagramPacket);
                            datagramSocket.close();
                        } catch (SocketException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        return datagramPacket;
                    }

                    @Override
                    protected void onPostExecute(DatagramPacket datagramPacket1) {
                        String string = "NG";

                        // 受信したデータはbyte配列なので、文字列に変換。
                        try {
                            string = new String(datagramPacket1.getData(), "SHIFT_JIS");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }

                        // 受信したデータを表示。
                        et.setText(string);
                    }
                };
                task.execute();
            }
        });
    }
}
```