liguofeng29’s blog

個人勉強用ブログだっす。

Androidのweb開発 - socket通信

Socket通信の概要

サーバ

  • ServerSocket(int port)
  • ServerSocket(int port, int backlog)
  • ServerSocket(int port, int backlog, InetAddress localAddr)

クライアント

  • Socket(InetAddress/String remoteAddress, int port)
  • Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort)

Socketのinputストリームとoutputストリーム

  • InputStream getInputStream() : データを取り出す
  • OutputStream getOutputStream() : データを流す

サーバを通して複数の人の間のチャットするサンプルコード

サーバ

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;


public class ChatServer {

    // クライアント接続Socketリスト
    public static ArrayList<Socket> socketList = new ArrayList<Socket>();

    public static void main(String[] args) throws IOException {
        // ポート番号31234でサーバ起動
        ServerSocket server = new ServerSocket(31234);

        while(true) {
            // 接続があった際
            Socket socket = server.accept();

            // リストに追加
            socketList.add(socket);

            // クライアントから接続があった場合、別スレッドを起動する
            new Thread(new ServerTread(socket)).start();
        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;



public class ServerTread implements Runnable{

    Socket socket = null;
    BufferedReader br = null;

    public ServerTread(Socket socket) throws UnsupportedEncodingException, IOException {
        this.socket = socket;

        // INPUTストリーム初期化
        br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
    }

    @Override
    public void run() {

        try{
            String content = null;

            while ((content = readFromClient()) != null) {

                // サーバのソケットリストを繰り返す
                for (Iterator<Socket> it = ChatServer.socketList.iterator(); it.hasNext();) {

                    Socket s = it.next();

                    try {
                        OutputStream os = s.getOutputStream();
                        os.write((content + "\n").getBytes("utf-8"));
                    } catch (SocketException e) {
                        e.printStackTrace();
                        // サーバのSocketリストから削除
                        it.remove();
                    }
                }
            }

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private String readFromClient() {
        try {
            return br.readLine();
        } catch (Exception e) {
            e.printStackTrace();
            // サーバのSocketリストから削除
            ChatServer.socketList.remove(socket);
        }

        return null;
    }
}

Android(クライアント)
① AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET"/>

② activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!-- チャット内容入力 -->
        <EditText
            android:id="@+id/input"
            android:layout_width="280dp"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/send"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="8dp"
            android:text="送信"/>
    </LinearLayout>
    <!-- サーバからのメッセージ受信 -->
    <TextView
        android:id="@+id/show"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="top"
        android:background="#ffff"
        android:textSize="14dp"
        android:textColor="#f000"/>
</LinearLayout>

③ MainActivity.java
ネット接続は別スレッドで起動する

package com.example.liguofeng.chatclient;

import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.view.View.OnClickListener;
import android.os.Handler;

public class MainActivity extends AppCompatActivity {

    EditText input;
    TextView show;
    Button send;
    Handler handler;

    // サーバと通信するスレッド
    ClientThread clientThread;

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

        // view取得
        input = (EditText) findViewById(R.id.input);
        send = (Button) findViewById(R.id.send);
        show = (TextView) findViewById(R.id.show);

        handler = new Handler()
        {
            @Override
            public void handleMessage(Message msg) {
                // サブスレッドからのメッセージ
                if (msg.what == 0x123) {
                    // 表示する
                    show.append("\n" + msg.obj.toString());
                }
            }
        };
        clientThread = new ClientThread(handler);
        // サーバ接続スレッド開始
        new Thread(clientThread).start();
        send.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    // メッセージ送信
                    Message msg = new Message();
                    msg.what = 0x345;
                    msg.obj = input.getText().toString();
                    clientThread.revHandler.sendMessage(msg);
                    // テキストクリア
                    input.setText("");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

④ ClientThread.java(別スレッド)

package com.example.liguofeng.chatclient;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class ClientThread implements Runnable {
    private Socket s;
    private Handler handler;
    public Handler revHandler;
    BufferedReader br = null;
    OutputStream os = null;

    public ClientThread(Handler handler) {
        this.handler = handler;
    }

    public void run() {
        try {
            s = new Socket("192.168.0.7", 31234);
            br = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            os = s.getOutputStream();
            // スレッド起動
            new Thread() {
                @Override
                public void run() {
                    String content = null;
                    // Socketのinputストリーム読み取り
                    try {
                        while ((content = br.readLine()) != null) {
                            // Mainスレッドに通知
                            Message msg = new Message();
                            msg.what = 0x123;
                            msg.obj = content;
                            handler.sendMessage(msg);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            // Lopper初期化
            Looper.prepare();
            revHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // UIスレッドメッセージ取得
                    if (msg.what == 0x345) {
                        // サーバにチャット内容送信
                        try {
                            os.write((msg.obj.toString() + "\r\n")
                                    .getBytes("utf-8"));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            // Looper起動
            Looper.loop();
        } catch (SocketTimeoutException e1) {
            System.out.println("TIME OUT!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

f:id:liguofeng29:20160108225614g:plain