Socket实现进程间通信

概述

Socket也称为“套接字”,是网络通信中的概念,它分为流式套接字和用户数举报套接字两种,分别对应于网络的传输控制层中的TCP和UDP协议。TCP协议是面向连接的协议,提供稳定的双向通信功能,TCP连接的简历需要经过”三次握手”才能完成为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性;而UDP是无连接的,提供不稳定的单向通信,当然UDP也可以实现双向通信功能。在性能上,UDP具有更好的效率,其缺点是不能保证数据一定能够正确传输,尤其是在网络拥塞的情况下。今天我们来演示一个跨进程的聊天程序,两个进程通过Socket实现信息的传输。

效果图

这里写图片描述

代码

我们先看服务端的代码

public class TCPServerService extends Service {

    private boolean mIsServiceDestoryed = false;
    private String[] mDefinedMessages = {"你好啊","你叫什么名字","今天天气不错","给你讲个笑话"};
    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(new TcpServer()).start();
    }

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

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
    private class TcpServer implements Runnable{

        private ServerSocket serverSocket;
        private Socket client;

        @Override
        public void run() {
            try {
                //服务端Socket对象
                serverSocket = new ServerSocket(8688);
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            while ((!mIsServiceDestoryed)){
                try {
                //不断监听客户端的请求,请求接收成功的话返回一个代表连接的对象
                    client = serverSocket.accept();
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            try {
                                responseClient(client);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public 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);
        }
        out.close();
        in.close();
        client.close();
    }
}

接下来是客户端代码

public class MainActivity extends AppCompatActivity{
    public static final int MSG_RECEIVE_NEW_MSG = 1;
    public static final int MSG_SOCKET_CONNECT = 2;
    private TextView tvMessage;
    private Socket socket;
    private EditText etMessage;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case MSG_SOCKET_CONNECT:
                    btn.setEnabled(true);
                    break;
                case MSG_RECEIVE_NEW_MSG:
                    tvMessage.setText(tvMessage.getText()+(String)msg.obj);
                    break;
            }
        }
    };
    private Button btn;
    private PrintWriter out;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMessage = (TextView) findViewById(R.id.tv_message);
        etMessage = (EditText) findViewById(R.id.et_message);
        btn = (Button) findViewById(R.id.btn);
        Intent intent = new Intent(this,TCPServerService.class);
        startService(intent);
        new Thread(){
            @Override
            public void run() {
                super.run();
                connectToTcpServer();
            }
        }.start();
    }
    public void click(View view){
        String content = etMessage.getText().toString();
        if(!TextUtils.isEmpty(content)&&out!=null){
            out.println(content);
            etMessage.setText("");
            String time = formatDateTime(System.currentTimeMillis());
            String msg = "client"+time+":"+content+"\n";
            tvMessage.setText(tvMessage.getText()+msg);
        }
    }

    public void connectToTcpServer(){
        while ((socket == null)) {
            try {
                socket = new Socket("localhost", 8688);
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                handler.sendEmptyMessage(MSG_SOCKET_CONNECT);
            }catch(IOException e){
                e.printStackTrace();
            }
        }
        //接受服务端消息
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (!MainActivity.this.isFinishing()){
                String str = in.readLine();
                if(str!=null){
                    String time = formatDateTime(System.currentTimeMillis());
                    String msg = "server"+time+str+"\n";
                    handler.obtainMessage(MSG_RECEIVE_NEW_MSG,msg).sendToTarget();
                }
            }
            in.close();
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(socket!=null){
            try {
                socket.shutdownInput();
                socket.close();
                } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public String formatDateTime(long time){
        return new SimpleDateFormat("(HH:MM:ss)").format(new Date(time));
    }
}

最后我们总结一下使用Socket通信的过程:
服务端:
1.使用端口号创建一个ServerSocket对象
2.调用accept函数监听客户端请求

客户端:
使用主机名和端口号创建一个Socket对象,注意这个端口号要和服务器的一致,不然无法建立连接

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值