一、实验目的
1.掌握Java中GUI程序的编写,包括事件监听机制。
2.掌握Java的网络通信编程,ServerSocket,Socket类的使用。
3.掌握Java中多线程的编程,Thread类,Runnable接口的使用。
4.掌握用面向对象的方法分析和解决复杂问题。
二、实验原理
编写程序完成以下功能:
1.设计一个基于GUI的客户-服务器的通信应用程序。
2.图1为Socket通信服务器端界面,点击该界面中的【Start】按钮,启动服务器监听服务(在图1界面中间的多行文本区域显示“Server starting…”字样)。图2为Socket通信客户端界面,点击该界面中的【Connect】按钮与服务器建立链接,并在图2所示界面中间的多行文本区域显示“Connect to server…”字样,当服务器端监听到客户端的连接后,在图1界面中间的多行文本区域追加一行“Client connected…”字样,并与客户端建立Socket连接。
3.当图1所示的服务器端和图2所示的客户机端建立Socket连接后,编程实现服务端、客户端之间的“单向通信”:在客户端的输入界面发送消息,在服务端接收该消息,并将接收到对方的数据追加显示在多行文本框中。
三、使用硬件、软件环境
PC 计算机一台,安装Windows10操作系统。
使用JCreator,JDK1.6.0等软件
四、实验过程、步骤及原始记录(算法、原程序、测试结果,分析等)
package Experiment;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class Server {
public static void main(String[] args) {
// TODO Auto-generated method stub
Myserver one = new Myserver();
one.myserver();
}
}
class Myserver{
public static ServerSocket serversocket = null;
public static Socket socket = null;
JTextArea main = new JTextArea(20,40);
public void myserver(){
JFrame myframe = new JFrame();
myframe.setBounds(600,100,500,500);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myframe.setTitle("服务器");
JPanel north = new JPanel();
north.setBorder(BorderFactory.createTitledBorder("服务器设置: "));
JTextField jta = new JTextField(30);
JLabel jl = new JLabel("Port:");
JButton jb = new JButton("Strat");
north.add(jl);
north.add(jta);
north.add(jb);
myframe.add(north,BorderLayout.NORTH);
JPanel center = new JPanel();
center.add(main);
myframe.add(center,BorderLayout.CENTER);
JPanel south = new JPanel();
JLabel jlk = new JLabel("Say");
JTextField jtr = new JTextField(30);
JButton jbv = new JButton("Say");
south.add(jlk);
south.add(jtr);
south.add(jbv);
myframe.add(south,BorderLayout.SOUTH);
myframe.setVisible(true);
jb.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0){
// TODO Auto-generated method stub
try {
main.append("Server starting.....\n");
serversocket = new ServerSocket(Integer.parseInt(jta.getText()));
socket = serversocket.accept();
main.append("Client connected......\n");
mythread xs = new mythread();
xs.start();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("错误");
}
}
});
jbv.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
DataOutputStream dox = new DataOutputStream(socket.getOutputStream());
String si = jtr.getText();
dox.writeUTF(si);
main.append("Server: "+si+"\n");
} catch (IOException e1) {
// TODO Auto-generated catch block
System.out.println("错误");
}
}
});
}
class mythread extends Thread{
public void run(){
try{
while(true){
DataInputStream di = new DataInputStream(socket.getInputStream());
String si = di.readUTF();
main.append("Client: "+si+"\n");
}
}catch(Exception e2){
System.out.println("错误");
}
}
}
}
package Experiment;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
import javax.swing.*;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Myclient one = new Myclient();
one.myclient();
}
}
class Myclient{
public Socket socket = null;
JTextArea main = new JTextArea(20,40);
public void myclient(){
JFrame myframe = new JFrame();
myframe.setBounds(100,100,500,500);
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myframe.setTitle("客户端");
JPanel north = new JPanel();
north.setBorder(BorderFactory.createTitledBorder("客户端设置: "));
JTextField jta = new JTextField(10);
JLabel jl = new JLabel("Server IP:");
JLabel jix = new JLabel("Server Port:");
JTextField jtax = new JTextField(10);
JButton jb = new JButton("Connect");
north.add(jl);
north.add(jta);
north.add(jix);
north.add(jtax);
north.add(jb);
myframe.add(north,BorderLayout.NORTH);
JPanel center = new JPanel();
center.add(main);
myframe.add(center,BorderLayout.CENTER);
JPanel south = new JPanel();
JLabel jlk = new JLabel("Say");
JTextField jtr = new JTextField(30);
JButton jbv = new JButton("Say");
south.add(jlk);
south.add(jtr);
south.add(jbv);
myframe.add(south,BorderLayout.SOUTH);
myframe.setVisible(true);
jb.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0){
// TODO Auto-generated method stub
try {
main.append("Connext to server......\n");
socket = new Socket(jta.getText(), Integer.parseInt(jtax.getText()));
mythread xs = new mythread();
xs.start();
}catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("错误");
}
}
});
jbv.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
try {
DataOutputStream dox = new DataOutputStream(socket.getOutputStream());
String si = jtr.getText();
dox.writeUTF(si);
main.append("Client: "+si+"\n");
} catch (IOException e1) {
// TODO Auto-generated catch block
System.out.println("错误");
}
}
});
}
class mythread extends Thread{
public void run(){
try{
while(true){
DataInputStream di = new DataInputStream(socket.getInputStream());
String si = di.readUTF();
main.append("Server: "+si+"\n");
}
}catch(Exception e2){
System.out.println("错误");
}
}
}
}
五、实验结论、分析、思考题与心得体会
分析:
在本次实验中,主要用到的是基于GUI的网络通信,首先是用JFrame和JPanel搭建平台,然后构筑每个部分的部件,定义文本框、标签和按钮等组件,再用布局管理器中的边界管理器,将各个部分组织好,网络通信的界面框架就搭建好了。
在这之后就是编写按钮的监听器,实现按钮的功能,connect和server两个按钮都是用于创建和连接服务器和客户端的,同时启动线程,线程是将对方的输入内容输出到自己这边的中间文本区域中。Say这个按钮是将文本框中的内容输入到对方的那里,并在自己这边的中间文本区域中输出。
实验心得:
在本次实验中,充分使用了我们在课程中所学的大部分知识,用Socket作为网络通信的方式,通过GUI设计构筑网络通信的基础,运用线程的知识作为网络通信顺利完成的关键,本次实验是对Java后半部分知识的综合运用的考察。
在这次实验中,给我留下最深刻印象的就是布局管理器的应用,在平常的作业中,并没有接触到布局管理器,而在这次实验中,让我明白了边界布局管理器的使用方法,深刻感受到了布局管理器的优越之处,可以使界面布局更合理、更美观,同时让我对JPanel类的使用有了更深的感触,与以往不同,在这次实验中,服务端与客户端都要定义三个JPanel类的变量,与在作业中的使用并不相同,这使我对这个的使用有了新的感悟。
最关键的是线程和监听器的使用,对监听器触发事件的编写,让我充分感受到监听器的便捷之处,更便于使用,而线程的编写则是使知识融会贯通,对线程的应用有了更深的理解。
本次实验与我们的生活息息相关,毕竟,在现代社会,完全脱离社交软件的人几乎是不存在的,这次实验让我们对平常使用的社交软件有了更深的理解,这并不是聊天软件唯一的编写方法,但对于帮助我们理解聊天软件的构成,有着极大的帮助。