項目展示--基於UDP傳輸協議+GUI的Java聊天小程序(圖片加源代碼)

前言

前幾天沒什麼事兒,在學習UDP和TCP傳輸協議,順手做了一個基於UDP協議的聊天小程序,同時複習了Java的GUI知識。

程序運行截圖展示

1.運行程序,生成第一個窗口,輸入要監聽的端口號:1234(示例端口號)

在這裏插入圖片描述
2.再次運行程序,生成第二個聊天窗口,並且要輸入端口號:4321(示例端口號)
在這裏插入圖片描述

3.然後,兩個聊天窗口之間便可以對話了。
在這裏插入圖片描述

3.程序代碼解讀

首先,貼上全部代碼,稍後會慢慢解釋每一部分。
/**
 * 
 */
package com.bert.udp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
 
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
 
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 

/**
 * @author Bert
 * 2019.03.09
 */
public class GuiChat extends JFrame {
	
	private static final int DEFAULT_PORT = 8899;
	
	//把主窗口分爲 NORTH.CENTER.SOUTH 三部分
	private JLabel stateLB;                 //顯示監聽狀態
	private JTextArea centerTextArea;       //顯示聊天記錄
	private JPanel sourthPanel;             //最下面的面板
	private JTextArea inputTextArea; 		//聊天輸入框
	private JPanel bottomPanel;				//放置IP輸入框,按鈕等
	private JTextField ipTextField;   		//IP輸入框
	private JTextField remotePortTF;  		//端口號輸入框
	private JButton sendBT;					//發送按鈕
	private JButton clearBT;  				//清除按鈕
	private DatagramSocket datagramSocket;	//發送數據用的載體
	
	/*
	 * 在構造方法中完成界面初始化,Socket連接初始化,和建立監聽狀態
	 */
	public  GuiChat() {
		setUPUI();
		initSocket();
		setListener();
	}
	
	/*
	 * 在 main方法中創建一個GuiChat類的對象,便是運行了程序;
	 */
	public static void main(String [] args) {
		new GuiChat();
	}
	
	/*
	 * 初始化聊天界面
	 */
	private void setUPUI() {   //聊天頁面初始化
		 setTitle("GUI聊天程序---出自JaffyMore");					//窗口標題欄設置
		 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);		//窗口關閉時觸發動作:退出程序
		 setSize(400, 400);										//窗口默認尺寸設置
		 setResizable(false);									//窗口大小不允許改動
		 setLocationRelativeTo(null); 						    //窗口居中
		 
		 //設置窗口中的North部分
		 stateLB = new JLabel("當前還未啓動監聽");
		 stateLB.setHorizontalAlignment(JLabel.RIGHT);
		 
		 //窗口中的Center部分
		 centerTextArea = new JTextArea();
		 centerTextArea.setEditable(false);
		 centerTextArea.setBackground(new Color(211, 211, 211));
		 
		 //窗口中的South部分
		 sourthPanel = new JPanel(new BorderLayout());
		 inputTextArea = new JTextArea(5,20);
		 bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,5,5));
		 ipTextField = new JTextField("127.0.0.1",8);
		 remotePortTF = new JTextField(String.valueOf(DEFAULT_PORT),3);
		 sendBT =new JButton("發送");
		 clearBT = new JButton("清屏");
		 bottomPanel.add(ipTextField);
		 bottomPanel.add(remotePortTF);
		 bottomPanel.add(sendBT);
		 bottomPanel.add(clearBT);
		 
		 sourthPanel.add(new JScrollPane(inputTextArea),BorderLayout.CENTER);
		 sourthPanel.add(bottomPanel,BorderLayout.SOUTH);
		 
		 add(stateLB,BorderLayout.NORTH);
		 add(new JScrollPane(centerTextArea), BorderLayout.CENTER);
		 add(sourthPanel, BorderLayout.SOUTH);
		 setVisible(true);
		   
	}
	
	private void setListener() {//爲按鈕添加監聽事件
		sendBT.addActionListener(new ActionListener() {
			
			 
			public void actionPerformed(ActionEvent e) {
				 //獲取發送的目標IP和端口號
				final String ipAddress = ipTextField.getText();
				final String remotePort = remotePortTF.getText();
				//判斷IP地址和端口號是否爲空
				if(ipAddress == null ||ipAddress.trim().equals("")
						||remotePort == null || remotePort.trim().equals("")){
					JOptionPane.showMessageDialog(GuiChat.this, "請輸入IP地址和端口號");
					return;
		         }
				if(datagramSocket == null || datagramSocket.isClosed()) {
					JOptionPane.showMessageDialog(GuiChat.this, "監聽不成功");
					return;
				}
				
				//獲取需要發送的內容
				String sendContent = inputTextArea.getText();
				byte[] buf = sendContent.getBytes();
				try {
					//將發送的內容顯示到自己的聊天記錄中
					centerTextArea.append("我對" + ipAddress + ":" +
					 remotePort + "說 \n" + inputTextArea.getText() +"\n\n" );
					//添加內容後,使滾動條自動滾動到最低端
					centerTextArea.setCaretPosition(centerTextArea.getText().length());
					//發送數據
					DatagramPacket packet = new DatagramPacket(buf,buf.length,
							InetAddress.getByName(ipAddress),Integer.parseInt(remotePort));
					datagramSocket.send(packet);
					inputTextArea.setText("");
				}catch(IOException e1) {
					JOptionPane.showMessageDialog(GuiChat.this, "出錯了,本次發送失敗");
					e1.printStackTrace();
				}
				
			}
		});
		
		//爲ClearBT 按鈕添加事件監聽器
		clearBT.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent arg0) {
				 centerTextArea.setText("當前聊天內容爲空,哈哈哈");
				
			}
		});
	}
     
	
	private void initSocket() {
		 int port = DEFAULT_PORT;
		 while(true) {
			 try {
				 if(datagramSocket != null && !datagramSocket.isClosed()) {
					 datagramSocket.close();
				 }
				 try {
					 //判斷端口號範圍
					 port = Integer.parseInt(JOptionPane.showInputDialog(this,
							 "請輸入端口號","端口號",JOptionPane.QUESTION_MESSAGE));
					 if(port <1 || port >65535) {
						 throw new RuntimeException("端口號超出範圍" + port);
					 }
				 }catch(Exception e) {
					 JOptionPane.showMessageDialog(null, "你輸入的端口號不正確" );
					 continue;
				 }
				 
				 //啓動DataGramSocket
				 datagramSocket = new DatagramSocket(port);
				 startListen();
				 
				 stateLB.setText("正在監聽端口號:" + port);
				 break;
			
			 }catch(SocketException e) {
				 JOptionPane.showMessageDialog(this, "端口號已經被佔用,請重新輸入" );
				 stateLB.setText("當前還未啓動監聽");
			 }
		 }
	}
	
	
	private void startListen() { //創建線程進行消息接收
		new Thread() {
		   private DatagramPacket datagramPacket;
		   public void run() {
			   byte [] buf = new byte[1024];
			   //創建數據包
			   datagramPacket = new DatagramPacket(buf, buf.length);
			   while(!datagramSocket.isClosed()) {
				   try {
					   datagramSocket.receive(datagramPacket);
					   centerTextArea.append(datagramPacket.getAddress().getHostAddress()
							   + ":" + ((InetSocketAddress) datagramPacket.getSocketAddress()
							  ).getPort() +"對我說: \n" + new String(datagramPacket.getData(),0,datagramPacket.getLength())
							  +"\n\n" );
				   }catch(IOException e) {
					   e.printStackTrace();
				   }
			   }
		   }
		}.start();
	}
}

4.最後

恭祝大家前程似錦。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章