客戶端的實現效果
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-------------- ---");
}
}
本文配套源碼