Day26 基于UDP协议的数据传输

实现基于UDP协议的的,两个进程(两个java程序)互相发送,并接受各自发送的数据的功能。

//First的main方法

public class First {
    //定义表示发送方是否结束
    public static boolean isSendOff=false;
    //定义控制发送方结束的锁对象
    public static Object flag=new Object();

    public static void main(String[] args) throws SocketException, UnknownHostException {
        //创建用于发送和接收的Stocket对象
        DatagramSocket datagramSocket = new DatagramSocket(10010);
        //创建用于发送数据的任务对象

        //指定接收端的ip地址和端口号
        String hostname="127.0.0.1";
        int port =10086;
        FirstSend firstSend = new FirstSend(datagramSocket, hostname, port);
        //创建用于接收数据的任务对象
        FirstRecesive firstRecesive = new FirstRecesive(datagramSocket);
        //启动两个线程,分别运行发送和接收数据的任务
        new Thread(firstSend).start();
        new Thread(firstRecesive).start();
    }
}

//First的发送线程FirstSend

public class FirstSend implements Runnable {
    //创建发送方的Socket对象
    private DatagramSocket datagramSocket;
    //目标端Ip
    private InetAddress targetIp;
    //目标端端口号
    private int targetPort;

    //构造方法
    public FirstSend(DatagramSocket datagramSocket, String targetIp, int targetPort) throws UnknownHostException {
        this.datagramSocket = datagramSocket;
        this.targetIp = InetAddress.getByName(targetIp);
        this.targetPort = targetPort;
    }

    @Override
    public void run() {
        //键盘录入数据
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String data;
        try {//当发送不为空时
            while ((data=br.readLine())!=null) {
                //调用方法,发送数据
                sendData(data);
                //当输入886时结束进程
                if ("886".equals(data)){
                    synchronized (First.flag) {
                        First.isSendOff=true;//表示发送方结束了发送
                        break;
                    }
                }
        }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void sendData(String data) throws IOException {
        byte[] byteData=data.getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(
                byteData,0,byteData.length,targetIp,targetPort);
        datagramSocket.send(datagramPacket);
    }
}

//First的接收线程FirstReesive

public class FirstRecesive implements Runnable {
    //创建接收方的Stocket对象
    private DatagramSocket datagramSocket;

    //构造接收方的方法
    public FirstRecesive(DatagramSocket datagramSocket) {
        this.datagramSocket = datagramSocket;
    }

    @Override
    public void run() {
        //创建接收数据的数据报包
        byte[] byteBuffer=new byte[1024];
        int off=0;
        DatagramPacket recesivePacket = new DatagramPacket(byteBuffer,off,byteBuffer.length-off);
        try {
        while (true){
            //接收数据,并将数据填充到接收数据的数据报包中
                datagramSocket.receive(recesivePacket);
            //从数据报包中获得数据并解析
            String s=getDataAnalysis(recesivePacket);
            if ("886".equals(s)){
                break;
            }
            }
        }catch (IOException e) {
                e.printStackTrace();
            }finally {
            while (true){
                synchronized (First.flag){
                    if (First.isSendOff){//如果发送方结束了
                        break;
                    }
                    //如果发送方没有结束,则等待100ms
                    try {
                        First.flag.wait(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }
    private String getDataAnalysis(DatagramPacket recesivePacket){
        byte[] byteData=recesivePacket.getData();
        int offset=recesivePacket.getOffset();
        int len=recesivePacket.getLength();
        //根据接收到的业务逻辑,分析获得数据
        String s=new String(byteData,offset,len);
        System.out.println("接收到了来自:"+recesivePacket.getAddress()+"--"+
        recesivePacket.getPort()+"的数据:"+s);
        return s;
    }
}

//Second类和First一样只是接收和发送的端口号port与Ip地址不同(这里相同都是本机)
//Second的main方法

public class Second {
    //定义表示发送方是否结束
    public static boolean isSendOff=false;
    //定义控制发送方结束的锁对象
    public static Object flag=new Object();

    public static void main(String[] args) throws SocketException, UnknownHostException {
        //创建用于发送和接收的Stocket对象
        DatagramSocket datagramSocket = new DatagramSocket(10086);
        //创建用于发送数据的任务对象

        //指定接收端的ip地址和端口号
        String hostname="127.0.0.1";
        int port =10010;
        FirstSend firstSend = new FirstSend(datagramSocket, hostname, port);
        //创建用于接收数据的任务对象
        FirstRecesive firstRecesive = new FirstRecesive(datagramSocket);
        //启动两个线程,分别运行发送和接收数据的任务
        new Thread(firstSend).start();
        new Thread(firstRecesive).start();
    }
}

//Second的发送线程SenondSend

public class SecondSend implements Runnable{
    //创建发送方的Socket对象
    private DatagramSocket datagramSocket;
    //目标端Ip
    private InetAddress targetIp;
    //目标端端口号
    private int targetPort;

    //构造方法
    public SecondSend(DatagramSocket datagramSocket, String targetIp, int targetPort) throws UnknownHostException {
        this.datagramSocket = datagramSocket;
        this.targetIp = InetAddress.getByName(targetIp);
        this.targetPort = targetPort;
    }

    @Override
    public void run() {
        //键盘录入数据
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String data;
        try {//当发送不为空时
            while ((data=br.readLine())!=null) {
                //调用方法,发送数据
                sendData(data);
                //当输入886时结束进程
                if ("886".equals(data)){
                    synchronized (Second.flag) {
                        Second.isSendOff=true;//表示发送方结束了发送
                        break;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void sendData(String data) throws IOException {
        byte[] byteData=data.getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(
                byteData,0,byteData.length,targetIp,targetPort);
        datagramSocket.send(datagramPacket);
    }
}

//Second的接收线程SecondRecesive

public class SecondRecesive implements Runnable {
    //创建接收方的Stocket对象
    private DatagramSocket datagramSocket;

    //构造接收方的方法
    public SecondRecesive(DatagramSocket datagramSocket) {
        this.datagramSocket = datagramSocket;
    }

    @Override
    public void run() {
        //创建接收数据的数据报包
        byte[] byteBuffer=new byte[1024];
        int off=0;
        DatagramPacket recesivePacket = new DatagramPacket(byteBuffer,off,byteBuffer.length-off);
        try {
            while (true){
                //接收数据,并将数据填充到接收数据的数据报包中
                datagramSocket.receive(recesivePacket);
                //从数据报包中获得数据并解析
                String s=getDataAnalysis(recesivePacket);
                if ("886".equals(s)){
                    break;
                }
            }
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            while (true){
                synchronized (Second.flag){
                    if (Second.isSendOff){//如果发送方结束了
                        break;
                    }
                    //如果发送方没有结束,则等待100ms
                    try {
                        Second.flag.wait(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }
    private String getDataAnalysis(DatagramPacket recesivePacket){
        byte[] byteData=recesivePacket.getData();
        int offset=recesivePacket.getOffset();
        int len=recesivePacket.getLength();
        //根据接收到的业务逻辑,分析获得数据
        String s=new String(byteData,offset,len);
        System.out.println("接收到了来自:"+recesivePacket.getAddress()+"--"+
                recesivePacket.getPort()+"的数据:"+s);
        return s;
    }
}

思路:根据UDP的传输过程一步一步实现,其中利用了锁对象完成了线程的同步,利用发送标志判断是否发送完毕以便于结束会话.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值