基于UDP協(xié)議實(shí)現(xiàn)聊天系統(tǒng)
基于UDP協(xié)議的聊天系統(tǒng)的實(shí)現(xiàn)(含GUI),供大家參考,具體內(nèi)容如下
這是一篇我的學(xué)習(xí)記錄,這學(xué)期加入了JAVA 的學(xué)習(xí),所以自己把教科書看了一下,然后嘗試地寫了一個(gè)UDP協(xié)議的聊天系統(tǒng),并且含GUI。因?yàn)閷?duì)JAVA和網(wǎng)絡(luò)的了解還不夠深,所以代碼還有許多地方需要完善。
代碼展示
下面展示一些 Client類。
/**-------------------
* 發(fā)送端
**---------------------*/
class Client extends Thread{
private static String content; //發(fā)送內(nèi)容
private static int port; //發(fā)送端口
private static int target; //目標(biāo)端口
private static byte[] addr; //目標(biāo)ip地址
/**-------------------
*構(gòu)造函數(shù)
**---------------------*/
public Client(String content,int port,int target,byte[] addr){
this.content=content;
this.port=port;
this.target=target;
this.addr=addr;
}
/**-------------------
*發(fā)送端函數(shù)
**---------------------*/
public void run(){
DatagramSocket client= null;
try {
//定義發(fā)送端端口為 port 的DatagramSocket對(duì)象
client = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
String str=content;
DatagramPacket packet= null;
try {
//定義DatagramPacket對(duì)象,用于封裝發(fā)送的數(shù)據(jù)以及目標(biāo)地址 target
packet = new DatagramPacket(str.getBytes(),str.getBytes().length,
InetAddress.getByAddress(addr),target);
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
//發(fā)送數(shù)據(jù)
client.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
//關(guān)閉釋放資源
client.close();
}
}
/**-------------------
*接收端
**---------------------*/
class Server extends Thread{
private static JTextArea jt; //對(duì)話框
private static int target; //目標(biāo)端口
/*-------------------
構(gòu)造函數(shù)
---------------------*/
public Server(JTextArea jt,int target){
this.jt=jt;
this.target=target;
}
下面展示一些 Server類。
/*-------------------
接收端
---------------------*/
class Server extends Thread{
private static JTextArea jt; //對(duì)話框
private static int target; //目標(biāo)端口
/*-------------------
構(gòu)造函數(shù)
---------------------*/
public Server(JTextArea jt,int target){
this.jt=jt;
this.target=target;
}
/*-------------------
接收端函數(shù)
---------------------*/
public void run(){
String str;
DatagramSocket server= null;
try {
//定義一個(gè)端口號(hào)為 target 的接收端DatagramSocket對(duì)象
server = new DatagramSocket(target);
} catch (SocketException e) {
e.printStackTrace();
}
byte[] buf=new byte[1024];
//定義一個(gè)DatagramPacket數(shù)據(jù)報(bào)對(duì)象,用于封裝接收數(shù)據(jù)
DatagramPacket packet=new DatagramPacket(buf, buf.length);
while (true){
try {
//等待接收數(shù)據(jù),在數(shù)據(jù)沒有被接收到之前會(huì)被堵塞
server.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
//使用DatagramPacket的方法獲得接收到的信息,并轉(zhuǎn)為字符串類型
str=new String(packet.getData(),
0,packet.getLength());
//將接收到的信息打印到對(duì)話框
jt.append("接收到:"+str+"\n");
}
}
}
下面展示一些 Main類。
public class Main {
public static int port;
public static int target;
public static byte[] addr;
public static void Login(){
System.out.print("請(qǐng)輸入端口號(hào):");
Scanner ScPort=new Scanner(System.in);
port=ScPort.nextInt();
System.out.print("請(qǐng)輸入目標(biāo)端口號(hào)1:");
Scanner ScTarget=new Scanner(System.in);
target=ScTarget.nextInt();
System.out.print("請(qǐng)輸入目標(biāo)端口號(hào)2:");
Scanner ScTarget2=new Scanner(System.in);
int target2=ScTarget2.nextInt();
System.out.print("請(qǐng)輸入目標(biāo)IP地址:");
Scanner Scaddr=new Scanner(System.in);
/*---------------------
將目標(biāo)IP存儲(chǔ)到數(shù)組中
-----------------------*/
String ip=Scaddr.nextLine();
/*---------------------
public String[] split(String regex):
根據(jù)給定正則表達(dá)式的匹配拆分此字符串
----------------------*/
String[] ii=ip.split("\\.");
/*---------------------
我們現(xiàn)在使用的IPv4是用一個(gè)32位的二進(jìn)制數(shù)來存儲(chǔ)的,為了方便記憶,
會(huì)將其分成4個(gè)8位的二進(jìn)制數(shù)(4個(gè)一字節(jié)的二進(jìn)制數(shù)),每8位之間用圓點(diǎn)隔開。
而每8位二進(jìn)制數(shù)可以轉(zhuǎn)換為一個(gè)0~255的十進(jìn)制數(shù),例如103.42.176.244,
這種寫法被稱為點(diǎn)數(shù)表示法
----------------------*/
byte[] addr=new byte[4];
for(int i=0;i<4;i++){
addr[i]=(byte)(Integer.parseInt(ii[i]));
}
System.out.println("窗口啟動(dòng)中....");
new Thread(new Server(CreateAndShowGUI(port,target,addr),target2),"接收服務(wù)").start();
}
/*-------------------
GUI界面
---------------------*/
public static JTextArea CreateAndShowGUI(int port,int target,byte[] addr){
/*---------------------
創(chuàng)建界面
----------------------*/
JFrame jf=new JFrame("聊天界面");
jf.setLocation(400,200);
jf.setSize(400,300);
/*---------------------
設(shè)置布局
----------------------*/
jf.setLayout(new BorderLayout());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/*---------------------
創(chuàng)建聊天窗口
----------------------*/
JTextArea jt=new JTextArea(14,34);
JScrollPane scrollPane=new JScrollPane(jt);
jt.setEditable(false);
/*---------------------
創(chuàng)建發(fā)送窗口
----------------------*/
JTextField jte=new JTextField(20);
JButton jb=new JButton("發(fā)送");
jb.addActionListener(e->{
String content=jte.getText();
/*---------------------
為發(fā)送按鈕創(chuàng)建動(dòng)作
----------------------*/
if (content!=null&&!content.trim().equals("")){
/*-------------------
判斷信息是否為空
若為空,在在對(duì)話框提示 你輸入的內(nèi)容為空
反之發(fā)送
--------------------*/
jt.append("輸入信息為:"+content+"\n");
/*--------------
將發(fā)送框信息發(fā)送到目標(biāo)對(duì)話框
傳入Client方法的參數(shù)分別為
“發(fā)送內(nèi)容,發(fā)送端口,目標(biāo)端口,目標(biāo)IP地址”
----------------*/
try {
new Thread(new Client(content,port,target,addr),"發(fā)送服務(wù)").start();
} catch (Exception exception) {
exception.printStackTrace();
}
}else{
jt.append("你輸入的內(nèi)容為空");
}
jte.setText(""); //信息發(fā)送后,將發(fā)送框重置
});
JPanel jp=new JPanel();
JLabel jl=new JLabel("聊天信息");
jp.add(jl);
jp.add(jte);
jp.add(jb);
jf.add(jt,BorderLayout.PAGE_START);
jf.add(jp,BorderLayout.PAGE_END);
//顯示GUI界面
jf.setVisible(true);
return jt;
}
public static void main(String[] args) throws Exception{
Login();
}
}
運(yùn)行截圖
登錄界面(一)

登錄界面(二)

聊天界面(一)

聊天界面(二)

總結(jié)
UDP協(xié)議是無連接通信,即在數(shù)據(jù)傳輸時(shí),數(shù)據(jù)的發(fā)送端和接收端不建立邏輯鏈接。也就是,當(dāng)一臺(tái)計(jì)算機(jī)想另外一臺(tái)計(jì)算機(jī)發(fā)送消息時(shí),發(fā)送端不會(huì)確定接收端是否存在,就會(huì)發(fā)送數(shù)據(jù)。同樣,接收端在接收到消息后也不會(huì)反饋發(fā)送端是否受到數(shù)據(jù)。但UDP消耗資源小、通訊效率高、延遲小。所以,雖然UDP是一個(gè)不可靠的協(xié)議,但它是分發(fā)信息的一個(gè)理想?yún)f(xié)議。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
spring bean.xml文件p標(biāo)簽使用報(bào)錯(cuò)的解決
這篇文章主要介紹了spring bean.xml文件p標(biāo)簽使用報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java swing實(shí)現(xiàn)的計(jì)算器功能完整實(shí)例
這篇文章主要介紹了Java swing實(shí)現(xiàn)的計(jì)算器功能,結(jié)合完整實(shí)例形式分析了java基于swing組件實(shí)現(xiàn)計(jì)算器布局與運(yùn)算功能的具體操作技巧,需要的朋友可以參考下2017-12-12
java項(xiàng)目中讀取jdbc.properties文件操作
這篇文章主要介紹了java項(xiàng)目中讀取jdbc.properties文件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Java版仿QQ驗(yàn)證碼風(fēng)格圖片驗(yàn)證碼
這篇文章主要為大家分享了java圖片驗(yàn)證碼實(shí)例代碼,感興趣的小伙伴們可以參考一下2016-04-04
Java thread.isInterrupted() 返回值不確定結(jié)果分析解決
這篇文章主要介紹了Java thread.isInterrupted() 返回值不確定結(jié)果分析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12
java使用Apache工具集實(shí)現(xiàn)ftp文件傳輸代碼詳解
這篇文章主要介紹了java使用Apache工具集實(shí)現(xiàn)ftp文件傳輸代碼詳解,分享了詳細(xì)連接ftp server和上傳文件,下載文件的代碼,以及結(jié)果展示,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
Java中Comparable與Comparator的區(qū)別解析
這篇文章主要介紹了Java中Comparable與Comparator的區(qū)別解析,實(shí)現(xiàn)Comparable接口,重寫compareTo方法,一般在實(shí)體類定義的時(shí)候就可以選擇實(shí)現(xiàn)該接口,提供一個(gè)默認(rèn)的排序方式,供Arrays.sort和Collections.sort使用,需要的朋友可以參考下2024-01-01
JAVA實(shí)現(xiàn)空間索引編碼——GeoHash的示例
本篇文章主要介紹了JAVA實(shí)現(xiàn)空間索引編碼——GeoHash的示例,如何從眾多的位置信息中查找到離自己最近的位置,有興趣的朋友可以了解一下2016-10-10

