Android客户端简单的聊天程序实现
Android客户端简单的聊天程序实现
看看今天实现的Android聊天室的聊天功能吧,先说说服务器端的代码及其功能吧
server.java : 负责服务器的界面,以及更服务器主线程ServerThread的启动,产生了BroadCast广播,产生ClientThread线程
ServerThread.java:服务器监听的端口线程,负责创建ServerSocket及监听是否有新的客户端连接,并记录客户端连接及需要发送的信息,产生了BroadCast广播
BroadCast.java: 服务器向客户端广播线程,负责向客户端发送消息,产生ClientThread线程
ClientThread.java:维持服务器和单个客户端的连接线程,负责接受客户端发来是信息
好了接着就看看他们的代码吧!!
1.server.java-------创建ServerThread对象启动run方法
- package com.wang;
- import java.awt.BorderLayout;
- import javax.swing.*;
- import java.awt.event.*;
- public class Server extends JFrame implements ActionListener {
- /****
- *服务器端主程序负责界面,以及服务段主线程ServerThread的启动
- * 服务端主线程ServerThread又产生BroadCast及ClientThread线程 建立服务器端主界面中所用到的布局方式
- ***/
- // 边框容器
- BorderLayout borderLayout1 = new BorderLayout();
- BorderLayout borderLayout2 = new BorderLayout();
- // 创建面板
- JPanel jPanel1 = new JPanel();
- JPanel jPanel2 = new JPanel();
- // 创建按钮
- JButton jButton1 = new JButton();
- JButton jButton2 = new JButton();
- JScrollPane jScrollPane1 = new JScrollPane();
- // 创建服务器端接收信息文本框
- static JTextArea jTextArea1 = new JTextArea();
- boolean bool = false, start = false;
- // 声明ServerThread线程类对象
- ServerThread serverThread;
- Thread thread;
- // 构造函数,用于初始化
- public Server() {
- super("Server");
- // 设置内容面板布局方式
- getContentPane().setLayout(borderLayout1);
- // 初始化按钮组件
- jButton1.setText("启动服务器");
- // 按钮的动作设置监听事件
- jButton1.addActionListener(this);
- jButton2.setText("关闭服务器");
- // 按钮的动作设置监听事件
- jButton2.addActionListener(this);
- // 初始化jPanel1面板对象,并向其中加入组件,上北
- this.getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
- jPanel1.add(jButton1);
- jPanel1.add(jButton2);
- // 初始化jPanel2面板对象,并向其中加入组件,
- jTextArea1.setText("");
- jPanel2.setLayout(borderLayout2);
- jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
- jScrollPane1.getViewport().add(jTextArea1);
- this.getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
- this.setSize(400, 400);
- this.setVisible(true);
- }
- public static void main(String[] args) {
- Server sever = new Server();
- sever.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
- // 服务器界面中按钮事件处理
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == jButton1) {
- // 声明一个ServerThread对象
- serverThread = new ServerThread();
- serverThread.start();
- } else if (e.getSource() == jButton2) {
- bool = false;
- start = false;
- serverThread.finalize();
- this.setVisible(false);
- }
- }
- }
2.ServerThread.java -----创建Broadcast对象,启动该线程,实现run方法后,不断的向客户端发送消息,ServerThread开启后,不断的获取新的客户端并监听是否发送消息
- package com.wang;
- import java.util.*;
- import java.io.*;
- import java.net.*;
- public class ServerThread extends Thread
- // 服务器监听端口线程
- {
- // 声明ServerSocket类对象
- ServerSocket serverSocket;
- // 指定服务器监听端口常量
- public static final int PORT = 80;
- /**
- * 创建一个Vector对象,用于存储客户端连接的ClientThread对象 , ClientThread类维持服务器与单个客户端的连接线程
- * 负责接收客户端发来的信息,clients负责存储所有与服务器建立连接的客户端
- **/
- Vector<ClientThread> clients;
- // 创建一个Vector对象,用于存储客户端发送过来的信息
- Vector<Object> messages;
- // BroadCast类负责服务器向客户端广播消息
- BroadCast broadcast;
- String ip;
- InetAddress myIPaddress = null;
- public ServerThread() {
- /***
- * 创建两个Vector数组非常重要 , clients负责存储所有与服务器建立连接的客户端,
- * messages负责存储服务器接收到的未发送出去的全部客户端的信息
- *
- **/
- clients = new Vector<ClientThread>();
- messages = new Vector<Object>();
- try {
- // 创建ServerSocket类对象
- serverSocket = new ServerSocket(PORT);
- } catch (IOException E) {
- }
- // 获取本地服务器地址信息
- try {
- myIPaddress = InetAddress.getLocalHost();
- } catch (UnknownHostException e) {
- System.out.println(e.toString());
- }
- ip = myIPaddress.getHostAddress();
- Server.jTextArea1.append("服务器地址:" + ip + "端口号:"
- + String.valueOf(serverSocket.getLocalPort()) + "\n");
- // 创建广播信息线程并启动
- broadcast = new BroadCast(this);
- broadcast.start();
- }
- /**
- * 注意:一旦监听到有新的客户端创建即new Socket(ip, PORT)被执行,
- * 就创建一个ClientThread来维持服务器与这个客户端的连接
- **/
- public void run() {
- while (true) {
- try {
- // 获取客户端连接,并返回一个新的Socket对象
- Socket socket = serverSocket.accept();
- System.out.println(socket.getInetAddress().getHostAddress());
- // 创建ClientThread线程并启动,可以监听该连接对应的客户端是否发送来消息, 并获取消息
- ClientThread clientThread = new ClientThread(socket, this);
- clientThread.start();
- if (socket != null) {
- synchronized (clients) {
- // 将客户端连接加入到Vector数组中保存
- clients.addElement(clientThread);
- }
- }
- } catch (IOException E) {
- System.out.println("发生异常:" + E);
- System.out.println("建立客户端联机失败!");
- System.exit(2);
- }
- }
- }
- public void finalize() {
- try {
- // 关闭serverSocket方法
- serverSocket.close();
- } catch (IOException E) {
- }
- serverSocket = null;
- }
- }
3.BroadCast.java------
- package com.wang;
- import java.io.*;
- public class BroadCast extends Thread { // 服务器向客户端广播线程
- ClientThread clientThread;
- // 声明ServerThread对象
- ServerThread serverThread;
- String str;
- public BroadCast(ServerThread serverThread) {
- this.serverThread = serverThread;
- }
- // 该方法的作用是不停地向所有客户端发送新消息
- public void run() {
- while (true) {
- try {
- // 线程休眠200 ms
- Thread.sleep(200);
- } catch (InterruptedException E) {
- }
- // 同步化serverThread.messages
- synchronized (serverThread.messages) {
- // 判断是否有未发的消息
- if (serverThread.messages.isEmpty()) {
- continue;
- }
- // 获取服务器端存储的需要发送的第一条数据信息
- str = (String) this.serverThread.messages.firstElement();
- }
- // 同步化serverThread.clients
- synchronized (serverThread.clients) {
- // 利用循环获取服务器中存储的所有建立的与客户端的连接
- for (int i = 0; i < serverThread.clients.size(); i++) {
- clientThread = (ClientThread) serverThread.clients
- .elementAt(i);
- try {
- // 向记录的每一个客户端发送数据信息
- clientThread.out.writeUTF(str);
- } catch (IOException E) {
- }
- }
- // 从Vector数组中删除已经发送过的那条数据信息
- this.serverThread.messages.removeElement(str);
- }
- }
- }
- }
4.ClientThread.java----获得Socket的输入输出流,向客户端接收或者发送数据
- package com.wang;
- import java.net.*;
- import java.io.*;
- public class ClientThread extends Thread
- {
- /**
- * 维持服务器与单个客户端的连接线程,负责接收客户端发来的信息,
- * 声明一个新的Socket对象,
- * 用于保存服务器端用accept方法得到的客户端的连接
- **/
- Socket clientSocket;
- //声明���务器端中存储的Socket对象的数据输入/输出流
- DataInputStream in = null;
- DataOutputStream out = null;
- //声明ServerThread对象
- ServerThread serverThread;
- public ClientThread(Socket socket,ServerThread serverThread)
- {
- clientSocket=socket;
- this.serverThread=serverThread;
- try
- {
- //创建服务器端数据输入/输出流
- in = new DataInputStream(clientSocket.getInputStream());
- out = new DataOutputStream(clientSocket.getOutputStream());
- }
- catch (IOException e2)
- {
- System.out.println("发生异常"+e2);
- System.out.println("建立I/O通道失败!");
- System.exit(3);
- }
- }
- //该方法监听该连接对应得客户端是否有消息发送
- public void run()
- {
- while(true)
- {
- try
- {
- //读入客户端发送来的信息
- String message=in.readUTF();
- synchronized(serverThread.messages)
- {
- if(message!=null)
- {
- //将客户端发送来得信息存于serverThread的messages数组中
- serverThread.messages.addElement(message);
- //在服务器端的文本框中显示新消息
- Server.jTextArea1.append(message+'\n');
- }
- }
- }
- catch(IOException E){break;}
- }
- }
- }
5.接着看看手机客户端的布局main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <EditText
- android:id="@+id/username"
- android:layout_width="270dp"
- android:layout_height="wrap_content"
- android:hint="请输入用户名:"
- android:maxLength="10" >
- </EditText>
- <Button
- android:id="@+id/LoginButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="登陆" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <EditText
- android:id="@+id/ip"
- android:layout_width="270dp"
- android:layout_height="wrap_content"
- android:digits=".1234567890"
- android:hint="10.254.1.62" >
- </EditText>
- <Button
- android:id="@+id/LeaveButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="退出" />
- </LinearLayout>
- <EditText
- android:id="@+id/history"
- android:layout_width="fill_parent"
- android:layout_height="280dp" >
- </EditText>
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <EditText
- android:id="@+id/message"
- android:layout_width="270dp"
- android:layout_height="wrap_content" >
- </EditText>
- <Button
- android:id="@+id/SendButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="发送" />
- </LinearLayout>
- </LinearLayout>
|
评论暂时关闭