基于UDP协议的聊天系统的实现(含GUI)
这是一篇我的学习记录,这学期加入了JAVA 的学习,所以自己把教科书看了一下,然后尝试地写了一个UDP协议的聊天系统,并且含GUI。因为对JAVA和网络的了解还不够深,所以代码还有许多地方需要完善。
代码展示
下面展示一些 Client类
。
/*-------------------
发送端
---------------------*/
class Client extends Thread{
private static String content; //发送内容
private static int port; //发送端口
private static int target; //目标端口
private static byte[] addr; //目标ip地址
/*-------------------
构造函数
---------------------*/
public Client(String content,int port,int target,byte[] addr){
this.content=content;
this.port=port;
this.target=target;
this.addr=addr;
}
/*-------------------
发送端函数
---------------------*/
public void run(){
DatagramSocket client= null;
try {
//定义发送端端口为 port 的DatagramSocket对象
client = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
String str=content;
DatagramPacket packet= null;
try {
//定义DatagramPacket对象,用于封装发送的数据以及目标地址 target
packet = new DatagramPacket(str.getBytes(),str.getBytes().length,
InetAddress.getByAddress(addr),target);
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
//发送数据
client.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
//关闭释放资源
client.close();
}
}
/*-------------------
接收端
---------------------*/
class Server extends Thread{
private static JTextArea jt; //对话框
private static int target; //目标端口
/*-------------------
构造函数
---------------------*/
public Server(JTextArea jt,int target){
this.jt=jt;
this.target=target;
}
下面展示一些 Server类
。
/*-------------------
接收端
---------------------*/
class Server extends Thread{
private static JTextArea jt; //对话框
private static int target; //目标端口
/*-------------------
构造函数
---------------------*/
public Server(JTextArea jt,int target){
this.jt=jt;
this.target=target;
}
/*-------------------
接收端函数
---------------------*/
public void run(){
String str;
DatagramSocket server= null;
try {
//定义一个端口号为 target 的接收端DatagramSocket对象
server = new DatagramSocket(target);
} catch (SocketException e) {
e.printStackTrace();
}
byte[] buf=new byte[1024];
//定义一个DatagramPacket数据报对象,用于封装接收数据
DatagramPacket packet=new DatagramPacket(buf, buf.length);
while (true){
try {
//等待接收数据,在数据没有被接收到之前会被堵塞
server.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
//使用DatagramPacket的方法获得接收到的信息,并转为字符串类型
str=new String(packet.getData(),
0,packet.getLength());
//将接收到的信息打印到对话框
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("请输入端口号:");
Scanner ScPort=new Scanner(System.in);
port=ScPort.nextInt();
System.out.print("请输入目标端口号1:");
Scanner ScTarget=new Scanner(System.in);
target=ScTarget.nextInt();
System.out.print("请输入目标端口号2:");
Scanner ScTarget2=new Scanner(System.in);
int target2=ScTarget2.nextInt();
System.out.print("请输入目标IP地址:");
Scanner Scaddr=new Scanner(System.in);
/*---------------------
将目标IP存储到数组中
-----------------------*/
String ip=Scaddr.nextLine();
/*---------------------
public String[] split(String regex):
根据给定正则表达式的匹配拆分此字符串
----------------------*/
String[] ii=ip.split("\\.");
/*---------------------
我们现在使用的IPv4是用一个32位的二进制数来存储的,为了方便记忆,
会将其分成4个8位的二进制数(4个一字节的二进制数),每8位之间用圆点隔开。
而每8位二进制数可以转换为一个0~255的十进制数,例如103.42.176.244,
这种写法被称为点数表示法
----------------------*/
byte[] addr=new byte[4];
for(int i=0;i<4;i++){
addr[i]=(byte)(Integer.parseInt(ii[i]));
}
System.out.println("窗口启动中....");
new Thread(new Server(CreateAndShowGUI(port,target,addr),target2),"接收服务").start();
}
/*-------------------
GUI界面
---------------------*/
public static JTextArea CreateAndShowGUI(int port,int target,byte[] addr){
/*---------------------
创建界面
----------------------*/
JFrame jf=new JFrame("聊天界面");
jf.setLocation(400,200);
jf.setSize(400,300);
/*---------------------
设置布局
----------------------*/
jf.setLayout(new BorderLayout());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/*---------------------
创建聊天窗口
----------------------*/
JTextArea jt=new JTextArea(14,34);
JScrollPane scrollPane=new JScrollPane(jt);
jt.setEditable(false);
/*---------------------
创建发送窗口
----------------------*/
JTextField jte=new JTextField(20);
JButton jb=new JButton("发送");
jb.addActionListener(e->{
String content=jte.getText();
/*---------------------
为发送按钮创建动作
----------------------*/
if (content!=null&&!content.trim().equals("")){
/*-------------------
判断信息是否为空
若为空,在在对话框提示 你输入的内容为空
反之发送
--------------------*/
jt.append("输入信息为:"+content+"\n");
/*--------------
将发送框信息发送到目标对话框
传入Client方法的参数分别为
“发送内容,发送端口,目标端口,目标IP地址”
----------------*/
try {
new Thread(new Client(content,port,target,addr),"发送服务").start();
} catch (Exception exception) {
exception.printStackTrace();
}
}else{
jt.append("你输入的内容为空");
}
jte.setText(""); //信息发送后,将发送框重置
});
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();
}
}
运行截图
登录界面(一)
登录界面(二)
聊天界面(一)
聊天界面(二)
总结
UDP协议是无连接通信,即在数据传输时,数据的发送端和接收端不建立逻辑链接。也就是,当一台计算机想另外一台计算机发送消息时,发送端不会确定接收端是否存在,就会发送数据。同样,接收端在接收到消息后也不会反馈发送端是否受到数据。但UDP消耗资源小、通讯效率高、延迟小。所以,虽然UDP是一个不可靠的协议,但它是分发信息的一个理想协议。