JAVA深化篇_38—— UDP通信的实现和项目案例

UDP通信的实现和项目案例

UDP通信实现原理

UDP协议与之前讲到的TCP协议不同,是面向无连接的,双方不需要建立连接便可通信。UDP通信所发送的数据需要进行封包操作(使用DatagramPacket类),然后才能接收或发送(使用DatagramSocket类)。

DatagramPacket:数据容器(封包)的作用

此类表示数据报包。 数据报包用来实现封包的功能。

常用方法:

方法名使用说明
DatagramPacket(byte[] buf, int length)构造数据报包,用来接收长度为 length 的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
getAddress()获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的
getData()获取发送或接收的数据
setData(byte[] buf)设置发送的数据

DatagramSocket:用于发送或接收数据报包

当服务器要向客户端发送数据时,需要在服务器端产生一个DatagramSocket对象,在客户端产生一个DatagramSocket对象。服务器端的DatagramSocket将DatagramPacket发送到网络上,然后被客户端的DatagramSocket接收。

DatagramSocket有两种常用的构造函数。一种是无需任何参数的,常用于客户端;另一种需要指定端口,常用于服务器端。如下所示:

  1. DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。
  2. DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。

常用方法:

方法名使用说明
send(DatagramPacket p)从此套接字发送数据报包
receive(DatagramPacket p)从此套接字接收数据报包
close()关闭此数据报套接字

UDP通信编程基本步骤:

  1. 创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
  2. 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
  3. 在服务器端定义DatagramPacket对象,封装待发送的数据包。
  4. 客户端将数据报包发送出去。
  5. 服务器端接收数据报包。

UDP通信入门案例

创建服务端

public class UDPServer {
  public static void main(String[] args) {
    //创建服务端接收数据的DatagramSocket对象
    try(DatagramSocket datagramSocket = new DatagramSocket(9999)){
      //创建数据缓存区
      byte[] b = new byte[1024];
      //创建数据报包对象
      DatagramPacket dp =new DatagramPacket(b,b.length);
      //等待接收客户端所发送的数据
      datagramSocket.receive(dp);
      String str = new String(dp.getData(),0,dp.getLength());
      System.out.println(str);
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

创建客户端

public class UDPClient {
  public static void main(String[] args) {
    //创建数据发送对象 DatagramSocket,需要指定消息的发送端口
    try(DatagramSocket ds = new DatagramSocket(8888)) {

      //消息需要进行类型转换,转换成字节数据类型。
      byte[] b = "打酱油".getBytes();

      //创建数据报包装对象DatagramPacket
      DatagramPacket dp = new DatagramPacket(b, b.length, new InetSocketAddress("127.0.0.1", 9999));

      //发送消息
      ds.send(dp);
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

UDP协议传递基本数据类型

创建服务端

public class BasicDataUDPServer {
    public static void main(String[] args) {

        try(DatagramSocket datagramSocket =new DatagramSocket(9999);){
            //创建字节数组缓冲区
            byte[] bytes = new byte[1024];
            //创建datagramPacket存放字节数组类型的数据
            DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);
            //等待客户端传入数据
            datagramSocket.receive(datagramPacket);
            //实现数据类型转换
            try(DataInputStream dataInputStream =new DataInputStream(new ByteArrayInputStream(bytes))){
                //通过基本数据数据流对象获取传递的数据
                System.out.println(dataInputStream.readLong());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

创建客户端

public class BasicDataUDPClient {
    public static void main(String[] args) {
        //创建发送数据的DatagramSocket对象
        try(DatagramSocket datagramSocket = new DatagramSocket(8856);
            //创建将基本数据类型转换为字节数组的ByteArrayOutputStream对象
            ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
            //创建将基本数据类型写入ByteArrayOutputStream中的数据输出流对象
            DataOutputStream dataOutputStream =new DataOutputStream(byteArrayOutputStream)){
            //要传递的数据
            long data=10000l;
            //写入ByteArrayOutputStream对象
            dataOutputStream.writeLong(data);
            //将基本数据类型转换为字节数组
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            //将字节数组包装到 DatagramPacket中
            DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length
            , new InetSocketAddress("127.0.0.1",9999));
            //发送数据
            datagramSocket.send(datagramPacket);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


传递自定义对象类型

创建Person类

/**
 * 当该对象需要在网络上传输时,一定要实现Serializable接口
 */
public class Person implements Serializable {
  private String name;
  private int age;


  public String getName() {
    return name;
   }


  public void setName(String name) {
    this.name = name;
   }


  public int getAge() {
    return age;
   }


  public void setAge(int age) {
    this.age = age;
   }


  @Override
  public String toString() {
    return "Person{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
   }
}

创建服务端

public class Person {
    public static void main(String[] args) {
        try(DatagramSocket datagramSocket =new DatagramSocket(9999);){

            byte[] bytes =new byte[1024];

            DatagramPacket datagramPacket =new DatagramPacket(bytes,bytes.length);
            //接收数据
            datagramSocket.receive(datagramPacket);

            //数据类型转换
            try (ObjectInputStream ois = new ObjectInputStream(
                    new ByteArrayInputStream(datagramPacket.getData()))){
                Person person = (Person)ois.readObject();
                System.out.println(person);

            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

创建客户端

public class ObjectTypeClient {
    public static void main(String[] args) {
        try(DatagramSocket datagramSocket =new DatagramSocket();
            ByteArrayOutputStream bos =new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos)){
            //实例化Person对象
            Person person =new Person();
            person.setAge(18);
            person.setName("zhangsan");
             //写入ByteArrayOutputStream对象
            oos.writeObject(person);
            //将自定义数据类型转换为字节数组类型
            byte[] byteArray = bos.toByteArray();
            //将自定义数据类型包装到DatagramPacket中
            DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length,
                                                 new InetSocketAddress("127.0.0.1",9999));
            //发送数据
            datagramSocket.send(datagramPacket);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值