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(); } }卑微求赞