Android小项目————聊天室(网络编程篇)
16lz
2021-01-25
Android小项目————聊天室(网络编程篇)
一.前言
这是关于聊天室的第二篇博客,内容主要是聊天室的核心篇章,即网络编程,主要是客户端和电脑端的服务器的代码。
二.客户端
- 步骤
- 创建一个ClientThread类
- 数据的流动
- 当按动发送键时,将数据从EditText中提取出来,通过Handler和Message传递给发送子线程。
- 发送子线程将数据(ip+昵称+输入语句)通过Socket和输出流发送给电脑端的服务器
- 服务器将数据通过Socket发送给所有连接服务器的手机客户端
- 手机的接受子线程接受来自客户端的数据
- 接受子线程通过Handler和Message传递给主线程
- 主线程将数据拆分,并赋值给msg对象,添加到Msg集合中,并更新UI
- 代码
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",""); } }}
三.服务器端
- 步骤
- 创建一个MyServer类(java编程,用eclipse)
- 创建一个ServerThread类
- 数据的流动
- 循环接受来自各个客户端的Socket链接
- 为每个链接创建一个子线程,并启动
- 子线程中循环接受来自该客户端的数据,并将该数据发送给所有客户端。
- 代码
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地址
- 源码百度云链接
更多相关文章
- “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
- Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理
- Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
- Android与JavaScript交互
- Android之搜索框+含搜索历史记录
- Android中ListView通过ContextMenu删除当前点击的一行数据
- android中json数据的解析