AndroidのSocket

7821 ワード

1. UDP
(1)アクセスネットワークには権限を追加しなければならない,アクセスネットワークには権限を追加しなければならない,アクセスネットワークには権限を追加しなければならない,重要なことは3回言う.
(2)簡単に述べる
UDPプロトコルはメッセージ向けで、簡単に言えば、UDPを利用してネットワークにアクセスするステップは「宅配便」です.DatagramPacket(速達)でデータとアドレスをパッケージし、DatagramSocket(あなた)でデータの送受信を行います.途中でどのように転送するかは、宅配便員のことです.私たちには関係ありません(そのため、UCPの伝送は信頼できません.バッグをなくす可能性があります.一部の宅配便と同じです).
InetAddress:アクセスするhostなどの情報を記録します.
DatagramPacket:パッケージデータとアクセスアドレスで、速達に相当します.
DatagramSocket:データ・レポートの送信と受信に使用され、速達の送信者と受信者に相当します.
(3)簡単な例
String serverIp = "111.111.111.11"; //     ip
InetAddress address = InetAddress.getByName(serverIp);
DatagramSocket socket = new DatagramSocket(8888); //                

//        UI    
new Thread() {
    @Override
    public void run() {
        try {
            //     
            String msg = "hello";
            byte[] msgBytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(msgBytes, msgBytes.length, mAddress, mPort);
            mSocket.send(packet);
            
            //     
            byte[] returnMsgBytes = new byte[1024];
            DatagramPacket returnPacket = new DatagramPacket(returnMsgBytes, returnMsgBytes.length, mAddress, mPort);
            // receive()      ,         
            mSocket.receive(returnPacket);
            
            String serverMsg = new String(returnPacket.getData(), 0, returnMsgBytes.length);
            Log.d("test", serverMsg);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}.start();

例から、UDPを使用することは、データのパッケージング、パケットの送受信の2つのステップであることがわかります.
2. TCP
(1)やはり権限、忘れないで
(2)簡単に述べる
UDPと異なり、TCPは接続に向いており、Socketオブジェクトを介して接続を作成し、入力ストリームと出力ストリームを取得し、接続を閉じる前にデータを送信および受信することができます.
プロセスは電話のようなもので、まず相手の電話番号(アクセス先)を入力し、電話をかけ(接続チャネルを作成)、それから話をし(データを送信)、あるいは相手の話を聞いて(データを受信)、最後に電話を切る(接続を閉じる).
TCPは接続を作成するときに3回握手し,接続を切断するときに4回手を振る.
(3)簡単な例
try {
    //     
    Socket socket = new Socket("111.111.111.11", 8888); //     111.111.111.11:8888
    //      (    )、   (    )
    InputStream inputStream = socket.getInputStream();
    OutputStream outputStream = socket.getOutputStream();

    final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));

    //     
    new Thread() {
        @Override
        public void run() {
            try {
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }.start();

    //     
    String line = "test";
    bw.write(line);
    bw.newLine();
    bw.flush();

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

UDPと異なり,TCPは接続を作成した後,接続を切断する前に直接入出力ストリームを介してデータを転送することができ,別途データをパッケージングする必要はないことがわかる.
(4)アンドロイドへの応用
Activity:
public class TCPActivity extends AppCompatActivity {

    //        
    private Button mSendBtn;
    //    
    private EditText mMsgEt;
    //           
    private TextView mContentTv;

    private TCPClientBiz mBiz = new TCPClientBiz();
    private boolean isConnected = false;

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

        initView();
        initEvent();

        mBiz.connect(new TCPClientBiz.OnConnectedListener() {
            @Override
            public void onSucceed() {
                //     
                isConnected = true;
            }
        });
    }

    private void initView() {
        mSendBtn = findViewById(R.id.send_btn);
        mMsgEt = findViewById(R.id.msg_et);
        mContentTv = findViewById(R.id.content_tv);
    }

    private void initEvent() {
        mSendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String msg = mMsgEt.getText().toString().trim();
                if (!msg.isEmpty()) {
                    if (isConnected) {
                        mMsgEt.setText("");
                        //     
                        mBiz.send(msg);
                    }
                }
            }
        });

        //         
        mBiz.setOnReceivedListener(new TCPClientBiz.OnReceivedListener() {
            @Override
            public void onReceived(String serverMsg) {
                mContentTv.append(formatMsg(serverMsg));
            }

            @Override
            public void onError(Exception e) {
                Toast.makeText(TCPActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    private String formatMsg(String msg) {
        return msg + "
"; } }

ビジネスクラス:
public class TCPClientBiz {

    private InputStream inputStream;
    private OutputStream outputStream;

    private Handler handler = new Handler(Looper.getMainLooper());

    //     ,        ,        
    public void connect(final OnConnectedListener onConnectedListener) {
        new Thread() {
            @Override
            public void run() {
                try {
                    Socket socket = new Socket("169.254.165.37", 9999);
                    inputStream = socket.getInputStream();
                    outputStream = socket.getOutputStream();
                    onConnectedListener.onSucceed();

                    while (true) {
                        //          
                        receive();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void receive() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            final String line;
            if ((line = br.readLine()) != null) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (onReceivedListener != null) {
                            onReceivedListener.onReceived(line);
                        }
                    }
                });
            }
        } catch (final IOException e) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (onReceivedListener != null) {
                        onReceivedListener.onError(e);
                    }
                }
            });
        }
    }

    public void send(final String msg) {
        new Thread() {
            @Override
            public void run() {
                try {
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
                    bw.write(msg);
                    bw.newLine();
                    bw.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private OnReceivedListener onReceivedListener;

    public void setOnReceivedListener(OnReceivedListener onReceivedListener) {
        this.onReceivedListener = onReceivedListener;
    }

    //       
    public interface OnReceivedListener {

        void onReceived(String serverMsg);

        void onError(Exception e);
    }

    //       
    public interface OnConnectedListener {
        void onSucceed();
    }
}

アンドロイドで運用するにはいくつかの点に注意する必要があります.第一に、接続は非同期で、コールバックを追加しなければなりません.そうしないと、空のポインタが異常になる可能性があります.第二に、ネットワーク操作ではよく言われる問題であり、UI操作はサブスレッドに注意しなければならない.