程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java聊天室小程序-客戶端代碼實現方面

Java聊天室小程序-客戶端代碼實現方面

編輯:關於JAVA

客戶端的實現效果

1.登錄服務器,如果服務器端口號和IP號輸入的字符都是"0"則,客戶端連接 到默認的服務器

2.輸入聊天昵稱

3.輸入"-quit"會自動退出聊天

4.輸入"-getList"會得到在線用戶的名稱

5.輸入"-to <用戶名稱> <聊天信息>"會把信息發送到指定的用 戶處,他人看不到

6.輸入"-help"會得到客戶端相應操作幫助

6.直接輸入內容則會將內容發送到所有在線的用戶處

客戶端的類與方法

1.建立連接方法:connectServer(String ip,int port)

2.斷開連接方法:disconnectServer()

2.發送消息方法:sendMes(String mes)

3.接受消息方法:getMes()

4.接受一次消息:getMesOnce()

5.獲得用戶列表:getList(String mes)

6.測試連接方法:testConnect(String ip,int port)

7.檢查用戶名 :checkNickName(String nickName)

8.獲得幫助列表:helpList();

9.各項內容的輸入在main方法中進行

重點注意的地方

由於客戶端無法知道服務器何時轉發數據,所以客戶端需要一直不停地監聽 消息,為了不影響其他的方法,如發送數據,這裡用到多線程,即為接受數據單 獨建立一個線程,以防止影響其他方法的正常工作。

package com.sunspot.udp.chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class Consumer implements Runnable{
  //發送數據的服務器Net地址,在fixServerLink
  //和sendMes方法中會用到
  private InetAddress sendAddress = null;
  private int port = 0;
  //客戶端
  private DatagramSocket client = null;
  //發送的數據報
  private DatagramPacket sendDatas = null;
  //用來測試是否能夠連接成功或者用戶名是否正確
  //在testConnect和checkNickName中會用到.
  //並穿插在sendMes方法中
  private boolean test = true;

  /**
   * 建立連接
   * @param ip   服務器IP號
   * @param port 服務器Port
   */
  public void connectServer(String ip,int port) {
   //先確定輸入的IP與端口號是否符合規則
   this.fixServerLink(ip,port);

   try {
    client = new DatagramSocket();
   } catch(SocketException s) {
    System.out.println("The Connection of server is error.");
   }
  }

  /**
   * 確定IP與Port輸入是否正確
   * @param ip
   * @param port
   */
  private void fixServerLink(String ip,int port) {
   //判斷連接服務器的端口號
   //如果輸入命令為0,則為默認端口號9999
   //否則端口號為新端口號
   if(port == 0)
    this.port = 9999;
   else
    this.port = port;
   //判斷連接服務器的IP地址
   //如果輸入命令為0,則為默認的本地IP地址
   //否則為輸入的IP地址
   try {
    if(ip.equalsIgnoreCase("0"))
     this.sendAddress = InetAddress.getLocalHost();
    else
     this.sendAddress = InetAddress.getByName(ip);
   } catch (UnknownHostException u) {
    System.out.println("Sorry, IP address you put is not currect!");
   }
  }

  /**
  * 斷開連接
  */
  public void disconnectServer() {
   //當客戶端斷開連接之前,客戶端會向服務器端發送一個信息,
   //以便告訴服務器該客戶下線
   this.sendMes("-quit");
   if(client != null)
    client.close();

  }

 
  /**
   * 發送消息
   * @param mes
   */
  public void sendMes(String mes) {
   byte[] buf = mes.getBytes();
   sendDatas = new DatagramPacket (buf,buf.length,sendAddress,port);
   //當建立發送時,測試正常
   test = true;
   try {
    client.send(sendDatas);
   } catch (NullPointerException n) {
    //如果無法得到要發送的消息,測試終止
    test = false;
    System.out.println("The nullity of the address of connection");
   } catch (IOException s) {
    //如果無法發送消息至服務器,測試終止
    test = false;
    System.out.println("There is a problem to send message.");
   } finally {
   }
  }

  /**
  * 得到數據
  */
  public void getMes() {
   byte[] buf = new byte[1024];
   DatagramPacket getDatas = new DatagramPacket (buf,buf.length);
   String mes = null;
   try {
    while(true) {
     client.receive(getDatas);
     mes = new String(buf,0,getDatas.getLength());
     //如果服務器發送的消息中的頭片段有-getList
     //表明客戶端獲得在線用戶列表,調用getList方法解析
     if(mes.indexOf("-getList") == 0)
      this.getList(mes);
     else
      System.out.println(mes);
    }
   } catch (IOException i) {
    System.out.println("Fail in receving message");
   }
  }

  /**
   * 得到一次數據
   *
   */
  public String getMesOnce() {
   byte[] buf = new byte[1024];
   DatagramPacket getDatas = new DatagramPacket (buf,buf.length);
   String mes = null;
   try {
    client.receive(getDatas);
    mes = new String(buf,0,getDatas.getLength());
   } catch (Exception e) {
    System.out.println("!-Can not receive the message!");
   } finally {
   }
   return mes;
  }

 
  /**
   * 顯示在線用戶列表
   * @param mes
   */
  private void getList(String mes) {
   String[] list = mes.split(",");
   System.out.println("在線用戶:\n-------------");
   for(int i = 1;i<list.length;i++) {
    System.out.println("  * "+list[i]);
   }
   System.out.println("-------------");
  }

  /**
   * 測試連接
   * @param ip
   * @param port
   * @return
   */
  public boolean testConnect(String ip,int port) {
   //創建連接,測試連接是否正確
   this.connectServer(ip,port);
   //如果連接正確,試圖發送測試標識"-test"
   //在發送數據過程中測試連接是否正確
   this.sendMes("-test");
   //如果連接發送測試通過
   //則開始測試是否能夠正確
   if (test) {
    String mes = this.getMesOnce();
    //如果服務器返回相應的標識,測試通過
    if (mes.startsWith("-test")) {
     test = true;
    }
   }

   if(client != null) {
    client.close();
   }
   return test;
  }

  /**
  * 判斷用戶名輸入是否正確
  */
  private boolean checkNickName(String nickName) {
   test = true;
   String mes = null;
   //判斷昵稱是否符合約定
   for(int i = 0;i<nickName.length();i++) {
    char temp = nickName.charAt(i);
    //如果不符合,則終止測試
    if(!Character.isLetterOrDigit(temp)) {
     test = false;
     break;
    }
   }
   //如果通過約定,則試圖向服務器發送昵稱,進行判斷
   if (test) {
    this.sendMes("-nick "+nickName);
    mes = this.getMesOnce();
    //如果服務器返回"-nick"標識
    //說明測試昵稱失敗,終止測試
    if (mes.startsWith("-nick")) {
     test = false;
    }
   }

   System.out.println(mes);
   return test;
  }

  /**
   * 得到幫助列表
   *
   */
  public void helpList() {
   System.out.println(
     "重要說明:如果已經成功連接,只要輸入內容,所有在線用戶都能看到您的發 言。"+"\n"+
     "-help"+"     獲取客戶端相應操作的幫助"+"\n"+
     "-test"+"     測試與服務器的連接,如果已經服務器連接,請不要選用此 項"+"\n"+
     "-getList"+"  得到在線用戶的列表"+"\n"+
     "-to <name> <message>" + "\n"+
     "          將消息發送到特定的在線用戶處"+"\n"+
     "-quit"+"     斷開連接,退出聊天室"+"\n"
   );
  }

  /**
  * 線程部分
  */
  public void run() {
   getMes();
  }

  /**
  * 各項內容的操作器
  */
  public static void main(String[] args) {
   Consumer consumer = new Consumer();
   String getIp = null;
   int getPort = 0;
   System.out.println("歡迎登錄Sunspot聊天室!");
   Scanner input = new Scanner(System.in);

   //輸入IP與Port
   boolean goahead = true;
   while(goahead) {
    System.out.println("1.請輸入服務器IP地址,默認請輸入數字0 :");
    //第一步:輸入服務器的IP地址
    getIp = input.next();
    //第二步:輸入服務器的端口號
    System.out.println("2.請輸入服務器端口號,默認請輸入數字0 :");
    try{
     getPort = input.nextInt();
    } catch(InputMismatchException i) {
     errorTip("!-The port style is not currect!");
    } catch(NoSuchElementException n) {
     errorTip("!-The port style is not currect!");
    }

    //測試服務器
    System.out.println("!-正在測試連接服務器,請稍候...");
    if(consumer.testConnect(getIp,getPort)) {
     System.out.println("!-連接成功!");
     goahead = false;
    } else
     System.out.println("!-連接失敗,您輸入的IP及端口號錯 誤。");
   }

   //連接服務器
   consumer.connectServer(getIp,getPort);

   //輸入昵稱
   boolean goon = true;
   while(goon) {
    //第三步:輸入昵稱
    System.out.println("3.請輸入您登錄後顯示的昵稱(只能輸入中文、 英文字母及數字):");
    String nick = input.next();
    boolean judge = consumer.checkNickName(nick);
    //判斷昵稱是否輸入正確
    if(judge)
     goon = false;
    else
     System.out.println("!-您輸入的用戶名不符合條件,請重新輸入 !");
   }

   //開始運行接收數據
   new Thread(consumer).start();
   //聊天
   String mes = null;
   System.out.println("!-您成功進入聊天室!");

   while(!(mes = input.nextLine()).equalsIgnoreCase("-quit")) {
    //如果輸入"-test"命令,開始測試
    if (mes.trim().equalsIgnoreCase("-test")) {
     consumer.testConnect(getIp, getPort);
    //-getList:獲得在線用戶列表
    } else if (mes.trim().equalsIgnoreCase("-getList")) {
     consumer.sendMes(mes);
    //-nick 設置昵稱
    } else if (mes.startsWith("-nick ")) {
     System.out.println("!-You have named, Can not allowed to rename!");
    //-help 獲得幫助列表
    } else if (mes.equalsIgnoreCase("-help")) {
     consumer.helpList();
    //如果輸入的是空字符,則不發送
    } else if (mes.equals("")) {
    } else {
     consumer.sendMes(mes);
    }
   }

   //退出
   input.close();
   consumer.disconnectServer();

  }

  /**
   * 錯誤提示標記
   * @param str
   */
  public static void errorTip(String str) {
   System.out.println("-----------------\n"+str+"\n-------------- ---");
  }
}

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved