Java實驗——基於GUI的網路通訊程式設計
一、實驗目的
1.掌握Java中GUI程式的編寫,包括事件監聽機制。
2.掌握Java的網路通訊程式設計,ServerSocket,Socket類的使用。
3.掌握Java中多執行緒的程式設計,Thread類,Runnable介面的使用。
4.掌握用物件導向的方法分析和解決複雜問題。
二、實驗原理
1.使用物件導向的設計方法設計程式
2.通過繼承JFrame類實現圖形化介面
3.通過事件監聽器實現按鈕點選監聽與觸發事件
4.利用ServerSocket和Socket類實現網路通訊
5.利用多執行緒技術實現同時讀入資料與傳送資料
三、使用硬體、軟體環境
硬體環境:PC計算機一臺,配置CPU為Intel(R)Core(TM)i7-8565U CPU @1.80Ghz記憶體為8.0GB,硬碟256G+1T(機械硬碟),安裝系統為Windows10作業系統。
軟體環境:IDEA,JDK12.0
四、實驗過程
①伺服器:
//Author:Sherlock Novitch in Hfut
// -*- codeing=utf-8 -*-
// @time:2020/10/19 15:14
// @File:ServerFrame.java
// @Software:IDEA
// @blog:https://blog.csdn.net/RealCoder
package experiment2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
public class ServerFrame extends JFrame {
private JTextField text1,text2; //text1為埠號文字欄,text2為訊息輸入欄
private JTextArea text; //訊息顯示區
private JButton button1,button2; //button1對應start,button2對應say
private ServerSocket server; //伺服器套接字
private Socket sc; //與客戶端建立聯絡的套接字
private DataInputStream in; //客戶端到伺服器的輸入流
private DataOutputStream out; //伺服器到客戶端的輸出流
private ReadThread readThread; //負責讀入資訊的執行緒
private myactionlistenr ac; //監聽兩個按鈕的監聽器
private ServerFrame(){ //構造方法
setLayout(new FlowLayout()); //窗體容器整體佈局設定為FlowLayout
GUIinit(); //呼叫元件初始化方法
eventinit(); //呼叫事件監聽器初始化方法
setVisible(true); //設定可視
setResizable(false); //設定不可更改大小
setDefaultCloseOperation(EXIT_ON_CLOSE); //在關閉窗體時,程式終止
}
private void GUIinit(){
setTitle("伺服器"); //設定標題
setBounds(100,250,500,300); //位置與大小
Box boxH1=Box.createHorizontalBox(); //建立水平盒式容器,後續依次從左到右新增"Port:",text1,button1;
Box boxH2=Box.createHorizontalBox(); //建立水平盒式容器,後續依次從左到右新增"Say: ",text2,button2;
Box boxV=Box.createVerticalBox(); //建立垂直盒式容器,後續依次從垂直方向從上向下新增"伺服器設定:",boxH1,boxH2
//1°開始新增“伺服器設定:”標籤至boxV
Box temp=Box.createHorizontalBox();
temp.add(new JLabel("伺服器設定:"));
temp.add(Box.createHorizontalStrut(400)); //新增水平支撐(類似Qt中的彈簧)
boxV.add(temp);
boxV.add(Box.createVerticalStrut(5));//新增垂直支撐(類似Qt中的彈簧)
//2°開始填裝boxH1,之後加入到boxV中
boxH1.add(new JLabel("Port:"));
boxH1.add(Box.createHorizontalStrut(5));
text1=new JTextField();
boxH1.add(text1);
boxH1.add(Box.createHorizontalStrut(10));
button1=new JButton("Start");
boxH1.add(button1);
boxV.add(boxH1);
boxV.add(Box.createVerticalStrut(10));
//3°開始新增文字顯示區至boxV
text=new JTextArea(9,30);
JScrollPane jScrollPane=new JScrollPane(text); //將text放置到滾動窗格(一種容器)中
text.setEditable(false);
jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
//當text內文字高度超過text高度時,text出現豎直滾動條
boxV.add(jScrollPane);
boxV.add(Box.createVerticalStrut(10));
//4°開始填裝boxH2,之後將boxH2加入到boxV中
boxH2.add(new JLabel("Say:"));
boxH2.add(Box.createHorizontalStrut(5));
text2=new JTextField();
boxH2.add(text2);
boxH2.add(Box.createHorizontalStrut(5));
button2=new JButton("Say");
boxH2.add(button2);
boxV.add(boxH2);
add(boxV);
}
private void eventinit(){
ac=new myactionlistenr(); //初始化監聽器
button1.addActionListener(ac); //監聽器註冊
button2.addActionListener(ac); //監聽器註冊
}
private void startserver(){ //”開啟服務“方法,當點選Start按鈕時,監聽器檢測到,呼叫此方法
try {
server = new ServerSocket(Integer.parseInt(text1.getText())); //用text1文字框內容對應的數字初始化伺服器套接字
text.append("Server starting…\n"); //伺服器端列印"Server starting…"
text.paintImmediately(text.getBounds()); //本條語句使得Server starting立即顯示出來
// 原因在於append方法只是將引數加至緩衝區
// 而本執行緒會被下一行accept方法阻塞
//呼叫paintImmediately方法直接將緩衝區內容顯示出來
sc = server.accept(); // 等待客戶端連線,初始化與客服端相連線的套接字物件sc
text.append("Client connected…\n"); //伺服器端列印”Client connected…“
in = new DataInputStream(sc.getInputStream()); //將in初始化為sc的輸入流
out = new DataOutputStream(sc.getOutputStream()); //將out初始化為sc的輸出流
readThread = new ReadThread(); //建立讀取資料的執行緒
readThread.start(); //讀取資料的執行緒開始執行
} catch (IllegalArgumentException e) { //若埠引數不符合,丟擲IllegalArgumentException,用訊息對話方塊提示使用者
JOptionPane.showMessageDialog(this,"埠值範圍必須為0~65535","警告",JOptionPane.WARNING_MESSAGE);
}catch (IOException e){
JOptionPane.showMessageDialog(this,"未知原因連線錯誤","警告",JOptionPane.WARNING_MESSAGE);
}catch (Exception e){
System.out.println(e.toString());
}
}
private void sentmessage(){ //當say按鈕被點選,監聽器檢測到,呼叫該方法
if(readThread==null){ //先判斷是否已連線,只需判斷readThread是否被建立,未建立則發出提示資訊,終止方法
JOptionPane.showMessageDialog(this,"未連線無法傳送資訊","警告",JOptionPane.WARNING_MESSAGE);
return;
}
try{
out.writeUTF("Server: "+text2.getText()+"\n"); //向客戶端傳送資訊
text.append("Server: "+text2.getText()+"\n"); //同時更新伺服器端文字區內容
text2.setText(""); //清空text2
}catch (IOException e){//異常處理
JOptionPane.showMessageDialog(this,"未知原因無法傳送資訊","警告",JOptionPane.WARNING_MESSAGE);
System.out.println(e.toString());
}
}
class myactionlistenr implements ActionListener { //監視按鈕的監聽器
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) startserver(); //如果點選的按鈕為start,呼叫startserver方法
if (e.getSource() == button2) sentmessage(); //如果點選的按鈕為say,則呼叫sentmessage方法
}
}
class ReadThread extends Thread{
public void run(){
while(true) {
try {
text.append(in.readUTF()); //將輸入流讀取的資料新增至文字顯示區
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}
public static void main(String[] args) {
ServerFrame sf=new ServerFrame();
}
}
②客戶端:
//Author:Sherlock Novitch in Hfut
// -*- codeing=utf-8 -*-
// @time:2020/10/19 15:14
// @File:ClientFrame.java
// @Software:IDEA
// @blog:https://blog.csdn.net/RealCoder
package experiment2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
public class ClientFrame extends JFrame {
private JTextField text1,text2,text3; //text1為ip地址輸入欄,text2為埠地址輸入欄,text3為訊息輸入欄
private JTextArea text; //文字顯示區
private JButton button1,button2; //button1為connect按鈕,button2為say按鈕
private Socket client; //客戶端套接字
private DataInputStream in; //從伺服器到客戶端的輸入流
private DataOutputStream out; //從客戶端到伺服器的輸出流
private ReadThread readThread; //讀取伺服器訊息的執行緒
private actionlistener ac; //監聽按鈕button1和button2的監聽器
private ClientFrame() { //構造方法
setLayout(new FlowLayout()); //窗體整體佈局為FlowLayout
GUIinit(); //呼叫元件初始化方法
Eventinit(); //呼叫事件初始化方法
setVisible(true); //設定可見
setResizable(false); //設定不可更改大小
setDefaultCloseOperation(EXIT_ON_CLOSE); //設定當關閉視窗時,程式終止
}
private void GUIinit(){ //元件初始化方法
setTitle("客戶端"); //設定標題
setBounds(600,250,500,300); //位置大小
Box boxH1=Box.createHorizontalBox(); //建立水平盒式容器,後續裝入"Server IP:",text1,"Server Port",button1;
Box boxH2=Box.createHorizontalBox(); //建立水平盒式容器,後續裝入"Say:",text3,button2;
Box boxV=Box.createVerticalBox(); //建立垂直盒式容器,後續裝入“客戶端設定:",boxH1,text,boxH2;
//1°boxV裝入“客戶端設定”標籤
Box temp=Box.createHorizontalBox();
temp.add(new JLabel("客戶端設定:"));
temp.add(Box.createHorizontalStrut(400));
boxV.add(temp);
boxV.add(Box.createVerticalStrut(5));
//2°將Server IP:",text1,"Server Port",button1從左到右加入到boxH1中,再講boxH1加入到boxV中
boxH1.add(new JLabel("Server IP:"));
boxH1.add(Box.createHorizontalStrut(5));
text1=new JTextField();
boxH1.add(text1);
boxH1.add(Box.createHorizontalStrut(10));
boxH1.add(new JLabel("Server Port:"));
boxH1.add(Box.createHorizontalStrut(5));
text2=new JTextField();
boxH1.add(text2);
boxH1.add(Box.createHorizontalStrut(5));
button1=new JButton("Connect");
boxH1.add(button1);
boxV.add(boxH1);
boxV.add(Box.createVerticalStrut(10));
//3°將text文字顯示區加入到滾動窗格並設定超高度出現豎直滾動條,再將滾動視窗加入到boxV中
text=new JTextArea(9,30);
JScrollPane jScrollPane=new JScrollPane(text);
text.setEditable(false);
jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
boxV.add(jScrollPane);
boxV.add(Box.createVerticalStrut(10));
//4°依次將從左到右“客戶端設定:",boxH1,text,boxH2加入到boxH2中,再將boxH3加入到boxV中
boxH2.add(new JLabel("Say:"));
boxH2.add(Box.createHorizontalStrut(5));
text3=new JTextField();
boxH2.add(text3);
boxH2.add(Box.createHorizontalStrut(5));
button2=new JButton("Say");
boxH2.add(button2);
boxV.add(boxH2);
add(boxV);
}
private void Eventinit(){
ac=new actionlistener();//初始化監聽器
button1.addActionListener(ac); //監聽器註冊
button2.addActionListener(ac); //監聽器註冊
}
private void startserver(){ //點選connect按鈕後呼叫的啟動客戶端服務的方法
try{
client=new Socket(); //初始化客戶端套接字
InetAddress address=InetAddress.getByName(text1.getText()); //用text1文字欄中的ip地址建立InetAddress
InetSocketAddress socketAddress=new InetSocketAddress(address,Integer.parseInt(text2.getText())); //所連線伺服器的地址
client.connect(socketAddress); //連線到伺服器
text.append("Connect to server…\n"); //文字顯示區新增“Connect to server…”
in=new DataInputStream(client.getInputStream()); //初始化輸入流
out=new DataOutputStream(client.getOutputStream()); //初始化輸出流
readThread=new ReadThread(); //建立讀取資料的執行緒
readThread.start(); //執行緒開始執行
}catch (UnknownHostException e){ //IP地址有誤,發出提示
JOptionPane.showMessageDialog(this,"輸入IP地址有誤","警告",JOptionPane.WARNING_MESSAGE);
}catch (IllegalArgumentException e) { //埠值非法,發出提示
JOptionPane.showMessageDialog(this,"埠值範圍必須為0~65535","警告",JOptionPane.WARNING_MESSAGE);
}
catch (IOException e) {
JOptionPane.showMessageDialog(this,"無法連線至埠","警告",JOptionPane.WARNING_MESSAGE);
}catch (Exception e){
System.out.println(e.toString());
}
}
private void sentmessage(){ //點選say按鈕呼叫的方法
if(readThread==null){ //先判斷是否已經連線至伺服器,若沒有,提示並終止方法
JOptionPane.showMessageDialog(this,"未連線無法傳送資訊","警告",JOptionPane.WARNING_MESSAGE);
return;
}
try{
out.writeUTF("Client: "+text3.getText()+"\n"); //傳送資訊至伺服器
text.append("Client: "+text3.getText()+"\n"); //客戶端文字顯示區新增剛發過的內容
text3.setText(""); //清空輸入欄
}catch (IOException e){
JOptionPane.showMessageDialog(this,"未知原因無法傳送資訊","警告",JOptionPane.WARNING_MESSAGE);
}
}
class actionlistener implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource()==button1) startserver(); //如果點選的按鈕是connect(button1),呼叫startserver方法
if(e.getSource()==button2) sentmessage(); //如果點選的按鈕是say(button2),呼叫sentmessage方法
}
}
class ReadThread extends Thread{ //讀取資料的執行緒
public void run(){
while(true){
try{
text.append(in.readUTF()); //讀入伺服器傳入的資訊,並顯示到文字顯示區
}catch (IOException e) {
System.out.println(e.toString());
}
}
}
}
public static void main(String[] args) {
ClientFrame cf=new ClientFrame();
}
}
卑微求贊
相關文章
- Java:基於TCP協議網路socket程式設計(實現C/S通訊)JavaTCP協議程式設計
- 網路通訊程式設計程式設計
- Socket網路程式設計基礎與實踐:建立高效的網路通訊程式設計
- 基於java博網即時通訊軟體的設計與實現Java
- Java進階:基於TCP通訊的網路實時聊天室JavaTCP
- UDP協議網路Socket程式設計(java實現C/S通訊案例)UDP協議程式設計Java
- [iptables] 基於iptables實現的跨網路通訊
- 基於java的網路招聘系統的設計與實現Java
- java多執行緒實現TCP網路Socket程式設計(C/S通訊)Java執行緒TCP程式設計
- Java網路程式設計UDP通訊原理Java程式設計UDP
- Java實驗六: Java流式程式設計與網路程式設計(頭歌)Java程式設計
- Python 基於 TCP 傳輸協議的網路通訊實現PythonTCP協議
- Java-GUI 程式設計之 SwingJavaGUI程式設計
- Java&Python的TCP&UDP通訊-網路程式設計JavaPythonTCPUDP程式設計
- Java實驗二:類程式設計實驗Java程式設計
- HUST-計算機網路實驗-socket程式設計計算機網路程式設計
- Socket程式設計入門(基於Java實現)程式設計Java
- 基於Select模型的通訊模擬--win32程式設計程式碼模型Win32程式設計
- [java併發程式設計]基於訊號量semaphore實現限流器Java程式設計
- 網路程式設計-Socket通訊程式設計
- GUI程式設計GUI程式設計
- Python GUI程式設計:tkinter關於ttkbootstrapPythonGUI程式設計boot
- 【java學習】GUI 圖形程式設計JavaGUI程式設計
- Java學習之AWT GUI程式設計JavaGUI程式設計
- Java-GUI程式設計之Swing元件JavaGUI程式設計元件
- java-GUI程式設計之AWT元件JavaGUI程式設計元件
- Java學習之Swing Gui程式設計JavaGUI程式設計
- 網路通訊基礎
- Java網路程式設計和NIO詳解9:基於NIO的網路程式設計框架NettyJava程式設計框架Netty
- 關於計算機網路的 Wireshark 實驗計算機網路
- 網路程式設計與通訊原理程式設計
- JAVASE網路程式設計之TCP實現聊天通訊Java程式設計TCP
- 【Java程式設計】Java上機實驗(三)Java程式設計
- Java-GUI程式設計之事件處理JavaGUI程式設計事件
- Java-GUI程式設計之選單元件JavaGUI程式設計元件
- GUI程式設計--班級資訊收集系GUI程式設計
- GUI程式設計--班級資訊收集系..GUI程式設計
- JAVA網路程式設計基礎Java程式設計