263 - 基于UDP的网络编程

本文详细介绍了如何使用UDP在Java中实现网站咨询聊天功能,包括单向通信、双向通信以及加入异常处理的完整过程。通过实例展示了DatagramSocket的使用和数据包的发送与接收,重点突出了双方地位平等的特点。
摘要由CSDN通过智能技术生成

小结 - 比较:

TCP:

客户端Socket  -  程序感受到的 使用流  :输出流

服务器端:ServerSocket -(获取)Socket     程序感受到的 使用流  :输入流

(客户端和服务器端地位不平等。)

UDP:

发送方:DatagramSocket   发送:数据包  DatagramPacket

接收方:DatagramSocket   接收:数据包  DatagramPacket

(发送方和接收方的地址是平等的。)

UDP案例:  完成网站的咨询聊天

功能分解1:单向通信

发送方:

package test6_UDP_1;

import java.io.IOException;
import java.net.*;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1
 * @version: 1.0
 */
public class TestSend { //发送方
    public static void main(String[] args) throws IOException {
        System.out.println("学生上线。。。");
        //1、准备套接字:指定发送方的端口号
        DatagramSocket ds = new DatagramSocket(8888);
        //2、准备数据包
        String str = "您好";
        byte[] bytes = str.getBytes(); //将String转为字节数组
        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
        */
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),9999);
        //要求传入的参数为:(byte[] buf, int length, InetAddress address,int port)

        //然后发送: —— 利用套接字进行发送
        ds.send(dp);

        //关闭资源
        ds.close();
    }
}

接收方:

package test6_UDP_1;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1
 * @version: 1.0
 */
public class TestReceive {//接收方

    public static void main(String[] args) throws IOException {
        System.out.println("老师上线了。。。");
        //1、创建套接字:指定接收方的端口
        DatagramSocket ds = new DatagramSocket(9999);
        //2、有一个空的数据包,打算用来接收 对方传过来的数据包
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,b.length); //传入空的数组
        //3.接收对方的数据包,然后放入我们的dp数据包中填充
        ds.receive(dp); //接收完以后,dp里面就填充好内容了

        //4、取出数据
        byte[] data = dp.getData(); // dp.getData()的返回值是字节数组
        //String s = new String(data);//将data字节数组转为字符串
        //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
        String s = new String(data,0,dp.getLength());
        System.out.println("学生对我说:"+s);

        //5、关闭资源
        ds.close();
    }
}

功能分解2:双向通信

发送方:

package test6_UDP_2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestSend { //发送方
    public static void main(String[] args) throws IOException {
        System.out.println("学生上线。。。");
        //1、准备套接字:指定发送方的端口号
        DatagramSocket ds = new DatagramSocket(8888);
        //2、准备数据包
        //键盘输入获取数据包
        Scanner sc = new Scanner(System.in);
        System.out.print("学生:"); //提示,且不换行
        String str = sc.next();
        byte[] bytes = str.getBytes(); //将String转为字节数组
        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
        */
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),9999);
        //要求传入的参数为:(byte[] buf, int length, InetAddress address,int port)

        //然后发送: —— 利用套接字进行发送
        ds.send(dp);

        //双向通信!!!

        //学生接收老师发送回来的信息:
        //同理,准备一个空的数据包,打算用来接收 对方(老师)传过来的数据包
        byte[] b = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(b,b.length); //传入空的数组
        //接收对方的数据包,然后放入我们的dp数据包中填充
        ds.receive(dp2); //接收完以后,dp里面就填充好内容了

        //4、取出数据
        byte[] data = dp2.getData(); // dp.getData()的返回值是字节数组
        //String s = new String(data);//将data字节数组转为字符串
        //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
        String s = new String(data,0,dp2.getLength());
        System.out.println("老师对我说:"+s);

        //关闭资源
        ds.close();
    }
}

接收方:

package test6_UDP_2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestReceive {//接收方

    public static void main(String[] args) throws IOException {
        System.out.println("老师上线了。。。");
        //1、创建套接字:指定接收方的端口
        DatagramSocket ds = new DatagramSocket(9999);
        //2、有一个空的数据包,打算用来接收 对方传过来的数据包
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,b.length); //传入空的数组
        //3.接收对方的数据包,然后放入我们的dp数据包中填充
        ds.receive(dp); //接收完以后,dp里面就填充好内容了

        //4、取出数据
        byte[] data = dp.getData(); // dp.getData()的返回值是字节数组
        //String s = new String(data);//将data字节数组转为字符串
        //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
        String s = new String(data,0,dp.getLength());
        System.out.println("学生对我说:"+s);

        //双向通信!!!

        //老师进行回复:
        //准备数据包
        //同样从 键盘输入获取数据包
        Scanner sc= new Scanner(System.in);
        System.out.print("老师:");
        String str = sc.next();//提示,且不换行
        byte[] bytes = str.getBytes(); //将String转为字节数组
        //封装数据,并且指定学生的ip和端口号
        DatagramPacket dp2 = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),8888);
        //发送:
        ds.send(dp2);

        //5、关闭资源
        ds.close();
    }
}

功能分解3:加入完整的处理异常方式

加入了 try-catch-finally 的异常处理。

发送方:

package test8_UDP_3_try_catch;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestSend { //发送方
    public static void main(String[] args) {
        System.out.println("学生上线。。。");
        //1、准备套接字:指定发送方的端口号
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(8888);

            //把下面的代码剪切到try中来
            //2、准备数据包
            //键盘输入获取数据包
            Scanner sc = new Scanner(System.in);
            System.out.print("学生:"); //提示,且不换行
            String str = sc.next();
            byte[] bytes = str.getBytes(); //将String转为字节数组
        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
        */
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),9999);
            //要求传入的参数为:(byte[] buf, int length, InetAddress address,int port)

            //然后发送: —— 利用套接字进行发送
            ds.send(dp); //有异常 ,则继续追加

            //双向通信!!!

            //学生接收老师发送回来的信息:
            //同理,准备一个空的数据包,打算用来接收 对方(老师)传过来的数据包
            byte[] b = new byte[1024];
            DatagramPacket dp2 = new DatagramPacket(b,b.length); //传入空的数组
            //接收对方的数据包,然后放入我们的dp数据包中填充
            ds.receive(dp2); //接收完以后,dp里面就填充好内容了

            //4、取出数据
            byte[] data = dp2.getData(); // dp.getData()的返回值是字节数组
            //String s = new String(data);//将data字节数组转为字符串
            //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
            String s = new String(data,0,dp2.getLength());
            System.out.println("老师对我说:"+s);

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            ds.close();
        }
    }
}

接收方:

package test8_UDP_3_try_catch;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestReceive {//接收方

    public static void main(String[] args) {
        System.out.println("老师上线了。。。");
        //1、创建套接字:指定接收方的端口
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(9999);

            //同样,把下面的代码剪切到try中来
            //2、有一个空的数据包,打算用来接收 对方传过来的数据包
            byte[] b = new byte[1024];
            DatagramPacket dp = new DatagramPacket(b,b.length); //传入空的数组
            //3.接收对方的数据包,然后放入我们的dp数据包中填充
            ds.receive(dp); //接收完以后,dp里面就填充好内容了

            //4、取出数据
            byte[] data = dp.getData(); // dp.getData()的返回值是字节数组
            //String s = new String(data);//将data字节数组转为字符串
            //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
            String s = new String(data,0,dp.getLength());
            System.out.println("学生对我说:"+s);

            //双向通信!!!

            //老师进行回复:
            //准备数据包
            //同样从 键盘输入获取数据包
            Scanner sc= new Scanner(System.in);
            System.out.print("老师:");
            String str = sc.next();//提示,且不换行
            byte[] bytes = str.getBytes(); //将String转为字节数组
            //封装数据,并且指定学生的ip和端口号
            DatagramPacket dp2 = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),8888);
            //发送:
            ds.send(dp2);

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //5、关闭资源
            ds.close();
        }
    }
}

功能分解4:正常通信

通信应该是连续的,不会一人说一句然后就中断/结束了(如上示代码)。

加入死循环 —— 可实现持续聊天

但是,怎么让停下来呢

停止会话由谁结束呢? 学生?老师?  : 学生

发送方:

package test9_UDP_4_complete_communication;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestSend { //发送方
    public static void main(String[] args) {
        System.out.println("学生上线。。。");
        //1、准备套接字:指定发送方的端口号
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(8888);

            while (true){ //死循环
                //把下面的代码剪切到try中来
                //2、准备数据包
                //键盘输入获取数据包
                Scanner sc = new Scanner(System.in);
                System.out.print("学生:"); //提示,且不换行
                String str = sc.next();

                /*//学生说了byebye,老师端就下线了,但是学生端还没下线呢
                //所以要:
                if (str.equals("byebye")){
                    System.out.println("学生也下线。。。");
                    break;
                }//运行后发现,学生端下线了,但是老师端没有正常下线
                 //原因:这段if判断的代码加错地方了,应该加在发送数据的代码后面*/

                byte[] bytes = str.getBytes(); //将String转为字节数组
            /*
            需要四个参数:
            1.指的是传送数据转为字节数组
            2.字节数组的长度
            3.封装接收方的ip
            4.指定接收方的端口号
            */
                DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),9999);
                //要求传入的参数为:(byte[] buf, int length, InetAddress address,int port)

                //然后发送: —— 利用套接字进行发送
                ds.send(dp); //有异常 ,则继续追加

                //学生说了byebye,老师端就下线了,但是学生端还没下线呢
                //所以要:
                if (str.equals("byebye")){
                    System.out.println("学生也下线。。。");
                    break;
                }//运行后发现,学生端下线了,但是老师端没有正常下线
                //原因:这段if判断的代码加错地方了,应该加在发送数据的代码后面

                //双向通信!!!

                //学生接收老师发送回来的信息:
                //同理,准备一个空的数据包,打算用来接收 对方(老师)传过来的数据包
                byte[] b = new byte[1024];
                DatagramPacket dp2 = new DatagramPacket(b,b.length); //传入空的数组
                //接收对方的数据包,然后放入我们的dp数据包中填充
                ds.receive(dp2); //接收完以后,dp里面就填充好内容了

                //4、取出数据
                byte[] data = dp2.getData(); // dp.getData()的返回值是字节数组
                //String s = new String(data);//将data字节数组转为字符串
                //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
                String s = new String(data,0,dp2.getLength());
                System.out.println("老师对我说:"+s);
            }
            
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            ds.close();
        }
    }
}

接收方:

package test9_UDP_4_complete_communication;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @Auther: zhoulz
 * @Description: test6_UDP_1 —— 分解2:双向通信
 * @version: 1.0
 */
public class TestReceive {//接收方

    public static void main(String[] args) {
        System.out.println("老师上线了。。。");
        //1、创建套接字:指定接收方的端口
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(9999);

            while (true){ //同样,加一个死循环
                //同样,把下面的代码剪切到try中来
                //2、有一个空的数据包,打算用来接收 对方传过来的数据包
                byte[] b = new byte[1024];
                DatagramPacket dp = new DatagramPacket(b,b.length); //传入空的数组
                //3.接收对方的数据包,然后放入我们的dp数据包中填充
                ds.receive(dp); //接收完以后,dp里面就填充好内容了

                //4、取出数据
                byte[] data = dp.getData(); // dp.getData()的返回值是字节数组
                //String s = new String(data);//将data字节数组转为字符串
                //取出数组包中的有效数据,dp.getLength() — 数组包中的有效长度
                String s = new String(data,0,dp.getLength());
                System.out.println("学生对我说:"+s);

                //如果学生说了byebye,老师端则就终止会话
                if (s.equals("byebye")){
                    System.out.println("学生已经下线了,老师也下线。。。");
                    break;
                }

                //双向通信!!!

                //老师进行回复:
                //准备数据包
                //同样从 键盘输入获取数据包
                Scanner sc= new Scanner(System.in);
                System.out.print("老师:");
                String str = sc.next();//提示,且不换行
                byte[] bytes = str.getBytes(); //将String转为字节数组
                //封装数据,并且指定学生的ip和端口号
                DatagramPacket dp2 = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("localhost"),8888);
                //发送:
                ds.send(dp2);
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //5、关闭资源
            ds.close();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值