Android小项目————聊天室(网络编程篇)

一.前言

这是关于聊天室的第二篇博客,内容主要是聊天室的核心篇章,即网络编程,主要是客户端和电脑端的服务器的代码。

二.客户端

  1. 步骤
    • 创建一个ClientThread类
  2. 数据的流动
    1. 当按动发送键时,将数据从EditText中提取出来,通过Handler和Message传递给发送子线程。
    2. 发送子线程将数据(ip+昵称+输入语句)通过Socket和输出流发送给电脑端的服务器
    3. 服务器将数据通过Socket发送给所有连接服务器的手机客户端
    4. 手机的接受子线程接受来自客户端的数据
    5. 接受子线程通过Handler和Message传递给主线程
    6. 主线程将数据拆分,并赋值给msg对象,添加到Msg集合中,并更新UI
  3. 代码
public class ClientThread implements Runnable {    private Socket mSocket;    private BufferedReader mBufferedReader = null;    private OutputStream mOutputStream = null;    private Handler mHandler;    public Handler revHandler;    public ClientThread(Handler handler) {        mHandler = handler;    }    @Override    public void run() {        try {            mSocket = new Socket("139.199.60.129", 9733);            Log.d("xjj","connect success");            //输入流管道到客户端            mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));            mOutputStream = mSocket.getOutputStream();//输出流,客户端到管道            //接受子线程            new Thread(){                @Override                public void run() {                    super.run();                    try {                        String content = null;                        //接收消息                        while ((content = mBufferedReader.readLine()) != null) {                            Log.d("xjj",content);                            //将接受到的数据传递给msg对象,并标记                            Message handleMsg = new Message();                            handleMsg.what = 0;                            handleMsg.obj = content;                            mHandler.sendMessage(handleMsg);                        }                    }catch (IOException e){                        e.printStackTrace();                    }                }            }.start();//启动            //Looper类用来为一个线程开启一个消息循环。            // 默认情况下android中新诞生的线程是没有开启消息循环的。            // (主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。)            Looper.prepare();            //绑定发送线程的Handler            revHandler = new Handler() {                @Override                public void handleMessage(Message msg) {                    if (msg.what == 1) {                        try {                            //发送消息                            String content;                            content =Name.IP+"#$#" + Name.name+"#$#" + msg.obj.toString() + "\r\n";                            mOutputStream.write(content.getBytes("utf-8"));                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                }            };            //Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。            Looper.loop();        } catch (IOException e) {            e.printStackTrace();            Log.d("xjj","");        }    }}

三.服务器端

  1. 步骤
    • 创建一个MyServer类(java编程,用eclipse)
    • 创建一个ServerThread类
  2. 数据的流动
    1. 循环接受来自各个客户端的Socket链接
    2. 为每个链接创建一个子线程,并启动
    3. 子线程中循环接受来自该客户端的数据,并将该数据发送给所有客户端。
  3. 代码
    MyServer类中
public class MyServer {    public static ArrayList mSocketList = new ArrayList<>() ;    public static void main(String[] args){        try {            //创建服务器Socket            ServerSocket ss = new ServerSocket(9733);            while (true){                //监听链接                Socket s = ss.accept();                //打印信息                System.out.println("ip:"+ s.getInetAddress().getHostAddress() +"加入聊天室");                //将s加入到线程池中                mSocketList.add(s);                //启动子线程                new Thread(new ServerThread(s)).start();            }        }catch (IOException e){            e.printStackTrace();            System.out.println("服务器已崩溃");            e.printStackTrace();        }    }}

ServerThread类中

public class ServerThread implements Runnable {    private Socket mSocket = null;    private BufferedReader mBufferedReader = null;    //构造方法    public ServerThread(Socket s)throws IOException{        mSocket = s;        //输入管道到服务器        mBufferedReader = new BufferedReader(new InputStreamReader(s.getInputStream(), "utf-8"));    }    public void run(){        try {            String content = null;            //循环接受服务器消息,如果没有接收到,说明该客户端下线,将其从线程池中删除            while ((content = mBufferedReader.readLine())!=null){                System.out.println("ip:"+ mSocket.getInetAddress().getHostAddress()+":"+content);                //循环向其他线程发送消息                 for (Iterator it = MyServer.mSocketList.iterator();it.hasNext();) {                Socket s = it.next();                try {                    OutputStream os = s.getOutputStream();                    os.write((content + "\n").getBytes("utf-8"));                } catch (SocketException e) {                    e.printStackTrace();                    it.remove();                    }                }            }        }catch (IOException e){            System.out.println("接收出错");            try {                mSocket.close();            } catch (IOException e1) {                e1.printStackTrace();            }            MyServer.mSocketList.remove(mSocket);            System.out.println("ip:"+ mSocket.getInetAddress().getHostAddress() +"退出聊天室");        }    }}

四.其他

  • 注意,在客户端中,创建Socket时我使用的ip为自己电脑的ip,如果需要正常运行,将代码中的ip换为自己电脑ip地址
  • 源码百度云链接

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理
  3. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  4. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  5. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  6. Android与JavaScript交互
  7. Android之搜索框+含搜索历史记录
  8. Android中ListView通过ContextMenu删除当前点击的一行数据
  9. android中json数据的解析

随机推荐

  1. Android定位相关
  2. 学习android上3D-opengl的一个不错的起点
  3. Android Animation动画实战(一): 从布局动画
  4. android/ios 手机移动开发(电子菜谱、健
  5. android通过webview组件实现与js相互调用
  6. Android(蓝牙)
  7. Android 黑科技之卸载系统应用(卸载流氓软
  8. Android界面设计基础:控件焦点4个步骤
  9. Android(安卓)Studio打包.so库到apk中
  10. android,ios之资源回收