【Android开发艺术】Socket进程间通信

【Android开发艺术】Socket进程间通信

前言:

 接下来大概很久都不会再写关于Android的文章了,毕竟要转去后端做开发了。这篇文章用来作为一个前后端的交接还是蛮不错的。毕竟Socket网络编程,平时都只是说说而已,不曾用过。许多时候,我写文章主要是用来巩固学习成果,比如今天做了什么,或者今天学了什么,或者之前学的东西快忘了赶紧记录下来。

正文:

一、关于socket可以看看这篇文章链接。

二、写个服务端App(Github代码提取点

举例:客户端App发消息到服务端App、服务端App实时回复功能。

package haibo.com.socketservel.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

public class TCPServerService extends Service {
    private boolean mIsServiceDestoryed = false;
    private final String TAG = "TCPServerService";
    private String[] mDefinedMsg = new String[]{
            "你好啊,哈哈",
            "请问你叫什么名字呀?",
            "你是哥哥还是妹妹?",
            "给你讲个笑话好不好"
    };

    public TCPServerService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG,"onCreate");
        new Thread(new TcpServer()).start();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        mIsServiceDestoryed = true;
        super.onDestroy();
    }

    private class TcpServer implements Runnable{

        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(8688);
            } catch (IOException e) {
                Log.e(TAG,"servel failed,port:8688");
                e.printStackTrace();
                return;
            }
            while (!mIsServiceDestoryed){
                try {
                    final Socket client = serverSocket.accept();
                    Log.e(TAG,"accept");
                    new Thread(){
                        @Override
                        public void run() {
                            try {
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void responseClient(Socket client) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        //这个true很重要啊
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
        out.println("欢迎来到聊天室");

        while (!mIsServiceDestoryed){
            String str = in.readLine();
            Log.e(TAG,"msg from client:"+str);
            if (str == null){
                break;
            }
            int i = new Random().nextInt(mDefinedMsg.length);
            String msg = mDefinedMsg[i];
            out.println(msg);
            Log.e(TAG,"send:"+msg);
        }
        Log.e(TAG,"client quit.");
        out.close();
        in.close();
        client.close();
    }


}
 第21到26行,定义String数组,用来返回数据给客户端。

第35行,启动一个子线程用来执行循环接收客户端的请求。

第49-80行,子线程的执行内容。55行通过ServerSocket创建Socket连接。63行获得socket对象。

private class TcpServer implements Runnable{

        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(8688);
            } catch (IOException e) {
                Log.e(TAG,"servel failed,port:8688");
                e.printStackTrace();
                return;
            }
            while (!mIsServiceDestoryed){
                try {
                    final Socket client = serverSocket.accept();
                    Log.e(TAG,"accept");
                    new Thread(){
                        @Override
                        public void run() {
                            try {
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 第82到103行,通过socket对象获得IO流。

通过inputstream获得客户端的输入流,通过outputStream写入服务端发给客户端的输出流(服务端随机发送消息给客户端)。

代码如下:

private void responseClient(Socket client) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        //这个true很重要啊
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
        out.println("欢迎来到聊天室");

        while (!mIsServiceDestoryed){
            String str = in.readLine();
            Log.e(TAG,"msg from client:"+str);
            if (str == null){
                break;
            }
            int i = new Random().nextInt(mDefinedMsg.length);
            String msg = mDefinedMsg[i];
            out.println(msg);
            Log.e(TAG,"send:"+msg);
        }
        Log.e(TAG,"client quit.");
        out.close();
        in.close();
        client.close();
    }

三、写个客户端App

package haibo.com.socketclient;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends Activity {
    private PrintWriter printWriter;
    private final String TAG = "MainActivity";

    private TextView content_tv;

    private EditText edit_query;

    private static boolean isFlag = false;

    private String content_msg;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    content_msg = "success connect";
                    Log.e(TAG,content_msg);
                    content_tv.setText(content_msg);
                    break;
                case 2:
                    Log.e(TAG, "receive:"+msg.obj);
                    content_msg=content_msg+"\n"+msg.obj;
                    content_tv.setText(content_msg);
                    break;
                case 3:
                    content_msg ="connect failed,retry...";
                    Log.e(TAG,content_msg);
                    content_tv.setText(content_msg);
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edit_query = (EditText) findViewById(R.id.edit_query);
        content_tv = (TextView) findViewById(R.id.content_tv);
        new Thread(){
            @Override
            public void run() {
                connectTCPServer();
            }
        }.start();
    }

    public void send(View view){
        String msg =edit_query.getText().toString().trim();
        if (!TextUtils.isEmpty(msg)&&printWriter!=null){
            printWriter.println(msg);
            content_msg=content_msg+"\n"+"client:"+msg;
            content_tv.setText(content_msg);
            Log.e(TAG, "client:"+msg);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isFlag = true;
    }

    private void connectTCPServer() {
        Socket socket = null;
        while (socket == null){
            try {
                socket = new Socket("localhost",8688);
                printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
                handler.sendEmptyMessage(1);
            } catch (IOException e) {
                SystemClock.sleep(1000);
                e.printStackTrace();
                handler.sendEmptyMessage(3);
            }

            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while (!MainActivity.isFlag){
                    //每一秒钟从服务端读取一次数据
                    SystemClock.sleep(1000);
                    String msg = br.readLine();
                    if (msg!=null){
                        String time = null;
                        SimpleDateFormat sdf= new SimpleDateFormat("HH:mm:ss");
                        time = sdf.format(new Date(System.currentTimeMillis()));
                        final String showedMsg = "server" +time +":"+msg+"\n";
                        handler.obtainMessage(2,showedMsg).sendToTarget();
                    }
                }
                Log.e(TAG, "client:"+"quit...");
                printWriter.close();
                br.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
第65-70行,和服务器建立socket连接。

new Thread(){
            @Override
            public void run() {
                connectTCPServer();
            }
        }.start();

其中第4行,connectTCPServer()方法如下:

private void connectTCPServer() {
        Socket socket = null;
        while (socket == null){
            try {
                socket = new Socket("localhost",8688);
                printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
                handler.sendEmptyMessage(1);
            } catch (IOException e) {
                SystemClock.sleep(1000);
                e.printStackTrace();
                handler.sendEmptyMessage(3);
            }

            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while (!MainActivity.isFlag){
                    //每一秒钟从服务端读取一次数据
                    SystemClock.sleep(1000);
                    String msg = br.readLine();
                    if (msg!=null){
                        String time = null;
                        SimpleDateFormat sdf= new SimpleDateFormat("HH:mm:ss");
                        time = sdf.format(new Date(System.currentTimeMillis()));
                        final String showedMsg = "server" +time +":"+msg+"\n";
                        handler.obtainMessage(2,showedMsg).sendToTarget();
                    }
                }
                Log.e(TAG, "client:"+"quit...");
                printWriter.close();
                br.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
第5行,主UI线程中直接建立连接会抛异常,所以需要在子线程中建立网络连接。

socket = new Socket("localhost",8688);
第6行,获得输出流,用来给服务端发送消息,写数据。

printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
第7行,建立连接。发送消息给handler,ui显示。

handler.sendEmptyMessage(1);
第15行,获得服务端发来的消息,获得输入流,死循环,从服务器端获取数据。每一秒钟读一次。

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
客户端UI展示如下:


本文,完。










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值