歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android客戶端簡單的聊天程序實現

Android客戶端簡單的聊天程序實現

日期:2017/3/1 10:14:08   编辑:Linux編程

看看今天實現的Android聊天室的聊天功能吧,先說說服務器端的代碼及其功能吧

server.java : 負責服務器的界面,以及更服務器主線程ServerThread的啟動,產生了BroadCast廣播,產生ClientThread線程

ServerThread.java:服務器監聽的端口線程,負責創建ServerSocket及監聽是否有新的客戶端連接,並記錄客戶端連接及需要發送的信息,產生了BroadCast廣播

BroadCast.java: 服務器向客戶端廣播線程,負責向客戶端發送消息,產生ClientThread線程

ClientThread.java:維持服務器和單個客戶端的連接線程,負責接受客戶端發來是信息

好了接著就看看他們的代碼吧!!

1.server.java-------創建ServerThread對象啟動run方法

  1. package com.wang;
  2. import java.awt.BorderLayout;
  3. import javax.swing.*;
  4. import java.awt.event.*;
  5. public class Server extends JFrame implements ActionListener {
  6. /****
  7. *服務器端主程序負責界面,以及服務段主線程ServerThread的啟動
  8. * 服務端主線程ServerThread又產生BroadCast及ClientThread線程 建立服務器端主界面中所用到的布局方式
  9. ***/
  10. // 邊框容器
  11. BorderLayout borderLayout1 = new BorderLayout();
  12. BorderLayout borderLayout2 = new BorderLayout();
  13. // 創建面板
  14. JPanel jPanel1 = new JPanel();
  15. JPanel jPanel2 = new JPanel();
  16. // 創建按鈕
  17. JButton jButton1 = new JButton();
  18. JButton jButton2 = new JButton();
  19. JScrollPane jScrollPane1 = new JScrollPane();
  20. // 創建服務器端接收信息文本框
  21. static JTextArea jTextArea1 = new JTextArea();
  22. boolean bool = false, start = false;
  23. // 聲明ServerThread線程類對象
  24. ServerThread serverThread;
  25. Thread thread;
  26. // 構造函數,用於初始化
  27. public Server() {
  28. super("Server");
  29. // 設置內容面板布局方式
  30. getContentPane().setLayout(borderLayout1);
  31. // 初始化按鈕組件
  32. jButton1.setText("啟動服務器");
  33. // 按鈕的動作設置監聽事件
  34. jButton1.addActionListener(this);
  35. jButton2.setText("關閉服務器");
  36. // 按鈕的動作設置監聽事件
  37. jButton2.addActionListener(this);
  38. // 初始化jPanel1面板對象,並向其中加入組件,上北
  39. this.getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
  40. jPanel1.add(jButton1);
  41. jPanel1.add(jButton2);
  42. // 初始化jPanel2面板對象,並向其中加入組件,
  43. jTextArea1.setText("");
  44. jPanel2.setLayout(borderLayout2);
  45. jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
  46. jScrollPane1.getViewport().add(jTextArea1);
  47. this.getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
  48. this.setSize(400, 400);
  49. this.setVisible(true);
  50. }
  51. public static void main(String[] args) {
  52. Server sever = new Server();
  53. sever.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  54. }
  55. // 服務器界面中按鈕事件處理
  56. public void actionPerformed(ActionEvent e) {
  57. if (e.getSource() == jButton1) {
  58. // 聲明一個ServerThread對象
  59. serverThread = new ServerThread();
  60. serverThread.start();
  61. } else if (e.getSource() == jButton2) {
  62. bool = false;
  63. start = false;
  64. serverThread.finalize();
  65. this.setVisible(false);
  66. }
  67. }
  68. }

2.ServerThread.java -----創建Broadcast對象,啟動該線程,實現run方法後,不斷的向客戶端發送消息,ServerThread開啟後,不斷的獲取新的客戶端並監聽是否發送消息

  1. package com.wang;
  2. import java.util.*;
  3. import java.io.*;
  4. import java.net.*;
  5. public class ServerThread extends Thread
  6. // 服務器監聽端口線程
  7. {
  8. // 聲明ServerSocket類對象
  9. ServerSocket serverSocket;
  10. // 指定服務器監聽端口常量
  11. public static final int PORT = 80;
  12. /**
  13. * 創建一個Vector對象,用於存儲客戶端連接的ClientThread對象 , ClientThread類維持服務器與單個客戶端的連接線程
  14. * 負責接收客戶端發來的信息,clients負責存儲所有與服務器建立連接的客戶端
  15. **/
  16. Vector<ClientThread> clients;
  17. // 創建一個Vector對象,用於存儲客戶端發送過來的信息
  18. Vector<Object> messages;
  19. // BroadCast類負責服務器向客戶端廣播消息
  20. BroadCast broadcast;
  21. String ip;
  22. InetAddress myIPaddress = null;
  23. public ServerThread() {
  24. /***
  25. * 創建兩個Vector數組非常重要 , clients負責存儲所有與服務器建立連接的客戶端,
  26. * messages負責存儲服務器接收到的未發送出去的全部客戶端的信息
  27. *
  28. **/
  29. clients = new Vector<ClientThread>();
  30. messages = new Vector<Object>();
  31. try {
  32. // 創建ServerSocket類對象
  33. serverSocket = new ServerSocket(PORT);
  34. } catch (IOException E) {
  35. }
  36. // 獲取本地服務器地址信息
  37. try {
  38. myIPaddress = InetAddress.getLocalHost();
  39. } catch (UnknownHostException e) {
  40. System.out.println(e.toString());
  41. }
  42. ip = myIPaddress.getHostAddress();
  43. Server.jTextArea1.append("服務器地址:" + ip + "端口號:"
  44. + String.valueOf(serverSocket.getLocalPort()) + "\n");
  45. // 創建廣播信息線程並啟動
  46. broadcast = new BroadCast(this);
  47. broadcast.start();
  48. }
  49. /**
  50. * 注意:一旦監聽到有新的客戶端創建即new Socket(ip, PORT)被執行,
  51. * 就創建一個ClientThread來維持服務器與這個客戶端的連接
  52. **/
  53. public void run() {
  54. while (true) {
  55. try {
  56. // 獲取客戶端連接,並返回一個新的Socket對象
  57. Socket socket = serverSocket.accept();
  58. System.out.println(socket.getInetAddress().getHostAddress());
  59. // 創建ClientThread線程並啟動,可以監聽該連接對應的客戶端是否發送來消息, 並獲取消息
  60. ClientThread clientThread = new ClientThread(socket, this);
  61. clientThread.start();
  62. if (socket != null) {
  63. synchronized (clients) {
  64. // 將客戶端連接加入到Vector數組中保存
  65. clients.addElement(clientThread);
  66. }
  67. }
  68. } catch (IOException E) {
  69. System.out.println("發生異常:" + E);
  70. System.out.println("建立客戶端聯機失敗!");
  71. System.exit(2);
  72. }
  73. }
  74. }
  75. public void finalize() {
  76. try {
  77. // 關閉serverSocket方法
  78. serverSocket.close();
  79. } catch (IOException E) {
  80. }
  81. serverSocket = null;
  82. }
  83. }

3.BroadCast.java------

  1. package com.wang;
  2. import java.io.*;
  3. public class BroadCast extends Thread { // 服務器向客戶端廣播線程
  4. ClientThread clientThread;
  5. // 聲明ServerThread對象
  6. ServerThread serverThread;
  7. String str;
  8. public BroadCast(ServerThread serverThread) {
  9. this.serverThread = serverThread;
  10. }
  11. // 該方法的作用是不停地向所有客戶端發送新消息
  12. public void run() {
  13. while (true) {
  14. try {
  15. // 線程休眠200 ms
  16. Thread.sleep(200);
  17. } catch (InterruptedException E) {
  18. }
  19. // 同步化serverThread.messages
  20. synchronized (serverThread.messages) {
  21. // 判斷是否有未發的消息
  22. if (serverThread.messages.isEmpty()) {
  23. continue;
  24. }
  25. // 獲取服務器端存儲的需要發送的第一條數據信息
  26. str = (String) this.serverThread.messages.firstElement();
  27. }
  28. // 同步化serverThread.clients
  29. synchronized (serverThread.clients) {
  30. // 利用循環獲取服務器中存儲的所有建立的與客戶端的連接
  31. for (int i = 0; i < serverThread.clients.size(); i++) {
  32. clientThread = (ClientThread) serverThread.clients
  33. .elementAt(i);
  34. try {
  35. // 向記錄的每一個客戶端發送數據信息
  36. clientThread.out.writeUTF(str);
  37. } catch (IOException E) {
  38. }
  39. }
  40. // 從Vector數組中刪除已經發送過的那條數據信息
  41. this.serverThread.messages.removeElement(str);
  42. }
  43. }
  44. }
  45. }

4.ClientThread.java----獲得Socket的輸入輸出流,向客戶端接收或者發送數據

  1. package com.wang;
  2. import java.net.*;
  3. import java.io.*;
  4. public class ClientThread extends Thread
  5. {
  6. /**
  7. * 維持服務器與單個客戶端的連接線程,負責接收客戶端發來的信息,
  8. * 聲明一個新的Socket對象,
  9. * 用於保存服務器端用accept方法得到的客戶端的連接
  10. **/
  11. Socket clientSocket;
  12. //聲明服務器端中存儲的Socket對象的數據輸入/輸出流
  13. DataInputStream in = null;
  14. DataOutputStream out = null;
  15. //聲明ServerThread對象
  16. ServerThread serverThread;
  17. public ClientThread(Socket socket,ServerThread serverThread)
  18. {
  19. clientSocket=socket;
  20. this.serverThread=serverThread;
  21. try
  22. {
  23. //創建服務器端數據輸入/輸出流
  24. in = new DataInputStream(clientSocket.getInputStream());
  25. out = new DataOutputStream(clientSocket.getOutputStream());
  26. }
  27. catch (IOException e2)
  28. {
  29. System.out.println("發生異常"+e2);
  30. System.out.println("建立I/O通道失敗!");
  31. System.exit(3);
  32. }
  33. }
  34. //該方法監聽該連接對應得客戶端是否有消息發送
  35. public void run()
  36. {
  37. while(true)
  38. {
  39. try
  40. {
  41. //讀入客戶端發送來的信息
  42. String message=in.readUTF();
  43. synchronized(serverThread.messages)
  44. {
  45. if(message!=null)
  46. {
  47. //將客戶端發送來得信息存於serverThread的messages數組中
  48. serverThread.messages.addElement(message);
  49. //在服務器端的文本框中顯示新消息
  50. Server.jTextArea1.append(message+'\n');
  51. }
  52. }
  53. }
  54. catch(IOException E){break;}
  55. }
  56. }
  57. }

5.接著看看手機客戶端的布局main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <LinearLayout
  7. android:layout_width="fill_parent"
  8. android:layout_height="wrap_content"
  9. android:orientation="horizontal" >
  10. <EditText
  11. android:id="@+id/username"
  12. android:layout_width="270dp"
  13. android:layout_height="wrap_content"
  14. android:hint="請輸入用戶名:"
  15. android:maxLength="10" >
  16. </EditText>
  17. <Button
  18. android:id="@+id/LoginButton"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:text="登陸" />
  22. </LinearLayout>
  23. <LinearLayout
  24. android:layout_width="fill_parent"
  25. android:layout_height="wrap_content"
  26. android:orientation="horizontal" >
  27. <EditText
  28. android:id="@+id/ip"
  29. android:layout_width="270dp"
  30. android:layout_height="wrap_content"
  31. android:digits=".1234567890"
  32. android:hint="10.254.1.62" >
  33. </EditText>
  34. <Button
  35. android:id="@+id/LeaveButton"
  36. android:layout_width="wrap_content"
  37. android:layout_height="wrap_content"
  38. android:text="退出" />
  39. </LinearLayout>
  40. <EditText
  41. android:id="@+id/history"
  42. android:layout_width="fill_parent"
  43. android:layout_height="280dp" >
  44. </EditText>
  45. <LinearLayout
  46. android:layout_width="fill_parent"
  47. android:layout_height="wrap_content"
  48. android:orientation="horizontal" >
  49. <EditText
  50. android:id="@+id/message"
  51. android:layout_width="270dp"
  52. android:layout_height="wrap_content" >
  53. </EditText>
  54. <Button
  55. android:id="@+id/SendButton"
  56. android:layout_width="wrap_content"
  57. android:layout_height="wrap_content"
  58. android:text="發送" />
  59. </LinearLayout>
  60. </LinearLayout>
Copyright © Linux教程網 All Rights Reserved