Socket实现进程间通信

1.Socket简单介绍

  • Socket可以实现进程间通信,Socket称为”套接字”,它分为流式套接字和用户数据套接字, 分别对应网络中的TCP和UDP协议。
  • TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立是通过三次握手才能完成,稳定性高,效率相对UDP较低。
  • UDP协议是面向无连接的,提供单向通信功能,效率高,不保证数据一定能够正确传输。
  • Android4.0以后不能在主线程中请求网络,会抛出异常NetworkOnMainThreadException。

2.客户端的实现

用Socket来进行进程间通信需要加上权限

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

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

MainActivity位于默认进程中

public class MainActivity extends Activity
{

    private static final int MESSAGE_RECEIVE_NEW_MSG = 1;

    private static final int MESSAGE_SOCKET_CONNECTED = 2;

    @InjectView(R.id.msg_container)
    TextView mMsgContainer;
    @InjectView(R.id.msg)
    EditText mMsg;
    @InjectView(R.id.send)
    Button mSend;
    private PrintWriter mPrintWriter;
    private Socket mClientSocket;


    private Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case MESSAGE_RECEIVE_NEW_MSG:
                {
                    mMsgContainer.setText(mMsgContainer.getText() + (String) msg.obj);
                    break;
                }
                case MESSAGE_SOCKET_CONNECTED: {
                    mSend.setEnabled(true);
                    break;
                }
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        clickEent();
        Intent service = new Intent(this, TcpService.class);
        startService(service);
        new Thread()
        {
            @Override
            public void run()
            {
                connectTCPServer();
            }
        }.start();
    }

    private void clickEent()
    {
        mSend.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                if (view== mSend)
                {
                    final String msg = mMsg.getText().toString();
                    if (!TextUtils.isEmpty(msg) && mPrintWriter != null)
                    {
                        mPrintWriter.println(msg);
                        mMsg.setText("");
                        String time = formatDateTime(System.currentTimeMillis());
                        final String showedMsg = "客户端" + time + ":" + msg + "\n";
                        mMsgContainer.setText(mMsgContainer.getText() + showedMsg);
                    }
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        if (mClientSocket != null) {
            try {
                mClientSocket.shutdownInput();
                mClientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        super.onDestroy();
    }

    private String formatDateTime(long time)
    {
        return new SimpleDateFormat("(HH:mm:ss)").format(new Date(time));
    }

    private void connectTCPServer()
    {
        Socket socket = null;
        while (socket == null)
        {
            try
            {
                socket = new Socket("localhost", 8088);
                mClientSocket = socket;
                mPrintWriter = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true);
                mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);
            }
            catch (IOException e)
            {
                SystemClock.sleep(1000);
            }
        }
        try
        {
            // 接收服务器端的消息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (!MainActivity.this.isFinishing())
            {
                String msg = br.readLine();
                if (msg != null) {
                    String time = formatDateTime(System.currentTimeMillis());
                    final String showedMsg = "服务端" + time + ":" + msg + "\n";
                    mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showedMsg).sendToTarget();
                }
            }
            Utils.close(mPrintWriter);
            Utils.close(br);
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.服务端的实现

TcpService位于私有进程中

 <service
          android:name=".service.TcpService"
          android:process=":remote"/>
public class TcpService extends Service
{ 
    private boolean mIsServiceDestoryed = false;

    private String[] mDefinedMessages = new String[] {
            "你好?",
            "请问你叫什么名字呀?",
            "吃饭了吗",
            "今天可以一起去看电影啊",
            "你的快递收到了吗",
            "今天北京的天气不错啊",
            "明天周末准备到哪玩啊?"
    };

    @Override
    public void onCreate() {
        new Thread(new TcpServer()).start();
        super.onCreate();
    }

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

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

    private class TcpServer implements Runnable {

        @SuppressWarnings("resource")
        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(8088);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }

            while (!mIsServiceDestoryed) {
                try {
                    // 接受客户端请求
                    final Socket client = serverSocket.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()));
        // 用于向客户端发送消息
        PrintWriter out = new PrintWriter(new BufferedWriter(
                new OutputStreamWriter(client.getOutputStream())), true);
        out.println("欢迎来到聊天室!");
        while (!mIsServiceDestoryed) {
            String str = in.readLine();
            if (str == null) {
                break;
            }
            int i = new Random().nextInt(mDefinedMessages.length);
            String msg = mDefinedMessages[i];
            out.println(msg);
        }
        // 关闭流
        Utils.close(out);
        Utils.close(in);
        client.close();
    }
}

4.下载地址和运行结果截图

运行结果截图:

这里写图片描述

下载地址:https://github.com/zeke123/Socket

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Socket是一种进程间通信的方法,它可以实现不同进程之间的通信和信息交换。Socket分为流式套接字和用户数据套接字,分别对应TCP和UDP协议。TCP协议是面向连接的,提供稳定的双向通信功能,而UDP协议是面向无连接的,提供单向通信功能。在Android中,由于主线程不能进行网络请求,所以需要在客户端的实现中使用Socket进行进程间通信。\[2\]另外,共享内存也是一种进程间通信的方式,它可以映射一段能被其他进程访问的内存,多个进程可以共享这段内存来实现通信和同步。共享内存是最快的IPC方式,通常与其他通信机制如信号量配合使用。\[3\]所以,Socket和共享内存都是实现进程间通信的有效方法。 #### 引用[.reference_title] - *1* *3* [socket本地多进程通信基本使用方法和示例](https://blog.csdn.net/qq_34597963/article/details/129355956)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Socket实现进程间通信](https://blog.csdn.net/u014005316/article/details/53419839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值