zoukankan      html  css  js  c++  java
  • 041 Android 基于TCP多线程通信实现群聊天的功能

    1.TCP多线程原理图

    2.实现方法

    (1)服务器端

    (2)客户端

    3.java后台代码

    主界面

    package com.lucky.test50socket2;
    
    import android.annotation.SuppressLint;
    import android.os.Handler;
    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;
    
    public class MainActivity extends AppCompatActivity {
        EditText editText;
        TextView textView2;
        Button button1;
        ClientThread clientThread;
    
        //handler实现页面与Socket的交互,handler获取ClientThread中发送的message
        @SuppressLint("HandlerLeak")
        Handler handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                if(msg.what==0x01){
                    textView2.setText(msg.obj.toString());
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            editText=findViewById(R.id.editText);
            textView2=findViewById(R.id.textView2);
            button1=findViewById(R.id.button);
            clientThread=new ClientThread(handler); //实例化ClientThread
            new Thread(clientThread).start();       //开启客户端的线程
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Message message=new Message(); //实例化一个message
                    message.what=0x02; //设置message的代号
                    message.obj=editText.getText().toString();//设置message的内容
                    ClientThread.handlerrev.handleMessage(message); //调用ClientThread的成员对象的方法,向服务器发送消息
                }
            });
    
        }
    }

    服务器

    package com.lucky.myserver;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Myserver {
        public static List<Socket> list; //定义一个存放socket的集合
        public static void main(String[] args) throws IOException {
            ServerSocket serverSocket=new ServerSocket(30004); //实例化一个服务器套接字
            //while设置为死循环,等待客户端的socket请求的到来
            while (true){
                Socket socket=serverSocket.accept(); //获取套接字
                list=new ArrayList<>();
                list.add(socket);
                ServerThead serverThead=new ServerThead(socket); //调用自建的ServerThead
                new Thread(serverThead).start(); //启动线程
            }
        }
    }

    服务器线程

    package com.lucky.myserver;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class ServerThead implements Runnable {
        private Socket socket;
        InputStream inputStream;  //输入流
        OutputStream outputStream;//输出流
        BufferedReader bufferedReader;
        //构造方法
        public ServerThead(Socket socket) throws IOException {
            this.socket=socket;
            inputStream=socket.getInputStream(); //获取输入流
            bufferedReader=new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
    
        }
    
        @Override
        public void run() {
            String str;
            while ((str=readData())!=null){
                for (Socket socket1 : Myserver.list) {
                    try {
                        outputStream=socket1.getOutputStream();
                        PrintStream printStream=new PrintStream(outputStream);
                        printStream.println(socket.getInetAddress()+":"+str);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private String readData(){
            try {
                return bufferedReader.readLine();
            } catch (IOException e) {
                Myserver.list.remove(socket); //删除套接字,避免占用内存
                return null;
            }
        }
    }

    客户端

    package com.lucky.test50socket2;
    
    import android.annotation.SuppressLint;
    import android.os.Looper;
    import android.os.Message;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.util.logging.Handler;
    
    
    public class ClientThread implements Runnable {
        android.os.Handler handler1; //天坑:注意要导入android.os.Handler,handler要两种类型
        InputStream inputStream;
        OutputStream outputStream;
        BufferedReader bufferedReader;
        static android.os.Handler handlerrev;
    
        //构造方法
        public ClientThread(android.os.Handler handler){
            this.handler1=handler;
        }
    
        @SuppressLint("HandlerLeak")
        @Override
        public void run() {
            try {
                Socket socket=new Socket("192.168.228.2",30004); //连接服务器
                inputStream=socket.getInputStream();//实例化输入流
                bufferedReader=new BufferedReader(new InputStreamReader(inputStream,"GBK"));
                new Thread(){
                    @Override
                    public void run() {
                        String string;
                        try {
                            while ((string=bufferedReader.readLine())!=null){
                                Message message=new Message(); //实例化一个消息,通过handler发送到前台
                                message.what=0x01; //数据的代号
                                message.obj=string; //发送的数据
                                //信息回传给主线程(主界面)显示
                                handler1.sendMessage(message);
                            }
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                }.start();
                /*
                 * 说明:如果要在非主线程中创建Handler对象,首先需要使用Looper类的prepare()方法来初始化一个Looper对象,
                 * 然后创建Handler对象,再使用Looper类的loop()方法启动Looper,从消息队列中获取和处理消息。
                 */
                Looper.prepare(); //准备handler
                outputStream=socket.getOutputStream();//实例化输出流
                handlerrev=new android.os.Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        if(msg.what==0x02){  //根据msg是否是需要发送的消息,若是,执行以下操作
                            String str=msg.obj.toString();
                            PrintStream printStream=new PrintStream(outputStream);
                            printStream.println(str); //将消息数据发送到服务器
                        }
                    }
                };
                Looper.loop(); //这句代码可以理解为循环执行run方法(最外层的run)
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    【BZOJ3626】【LNOI2014】—Lca(树链剖分)
    【BZOJ2434】【NOI2011】—阿狸的打字机(AC自动机+线段树)
    【UVA10498】—Happiness(线性规划/单纯形算法)
    【BZOJ4736】【清华集训2016】—温暖会指引我们前行(LCT)
    【BZOJ3451】【Tyvj1953】—Normal(点分治+NTT)
    【SCOI2019】—DAY2T1 湖之精灵的游戏(凸包+二分)
    【BZOJ4817】【SDOI2017】—树点涂色(LCT+树链剖分+线段树)
    【SCOI2019】—DAY2T1 RGB(容斥)
    Stargazer的分治讲义
    python datetime 模块
  • 原文地址:https://www.cnblogs.com/luckyplj/p/10539765.html
Copyright © 2011-2022 走看看