分析udp数据报_第十二章 Java网络编程(4)——UDP数据报

本文介绍了Java中基于UDP协议的网络通信,强调了UDP与TCP的区别,即UDP传输速度快但不保证可靠性。内容包括如何创建DatagramPacket发送和接收数据包,以及使用DatagramSocket进行通信。通过举例展示了两台主机之间使用UDP交换数据的过程。
摘要由CSDN通过智能技术生成

UDP数据报

套接字是基于TCP协议的网络通信,即客户端程序和服务器端程序是有连接的,双方的信息是通过程序中的输入、输出流来交互的,使得接收方收到信息的顺序和发送方发送信息的顺序完全相同,就像生活中双方使用电话进行信息交互一样。

本节介绍Java中基于UDP(用户数据报协议)协议的网络信息传输方式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。也就是说,数据在传输时,用户无法知道数据能否正确到达目的地主机,也不能确定数据到达目的地的顺序是否和发送的顺序相同。可以把UDP通信比作生活中的邮递信件,我们不能肯定所发的信件就一定能够到达目的地,也不能肯定到达的顺序是发出时的顺序,可能因为某种原因导致后发出的先到达。既然UDP是一种不可靠的协议,为什么还要使用它呢?如果要求数据必须绝对准确地到达目的地,显然不能选择UDP协议来通信。但有时候人们需要较快速地传输信息,并能容忍小的错误,就可以考虑使用UDP协议。

基于UDP通信的基本模式是:

  • 将数据打包(好比将信件装入信封一样),称为数据包,然后将数据包发往目的地。

  • 接收发来的数据包(好比接收信封一样),然后查看数据包中的内容。

发送数据包

用DatagramPacket类将数据打包,即用DatagramPacket类创建一个对象,称为数据包。用DatagramPacket的以下两个构造方法创建待发送的数据包。

DatagramPacket (byte data[], int length, InetAddtress address, int port)

使用该构造方法创建的数据包对象具有下列两个性质:

  • 含有data数组指定的数据。

  • 该数据包将发送到地址是address,端口号是port的主机上。

称address是这个数据包的目标地址,port是它的目标端口。

DatagramPack(byte data[], int offset, int length, InetAddtress address, int port)

使用该构造方法创建的数据包对象含有数组data中从offset开始后的length个字节,该数据包将发送到地址是address,端口号是port的主机上。例如:

byte data[] ="生日快乐".getBytes();InetAddtress address = InetAddtress.getName("www.china.com.cn");DatagramPacket data_pack = new DatagramPacket(data,data.length, address,2009);

注:对于用上述方法创建的用于发送的数据包,data_pack如果调用方法public int getPort()可以获取该数据包目标端口;调用方法public InetAddress getAddress()可获取这个数据包的目标地址;调用方法public byet[] getData()可以返回数据包中的字节数组。

用DatagramSocket类的不带参数的构造方法DatagramSocket()创建一个对象,该对象负责发送数据包。例如:

DatagramSocket mail_out= new DatagramSocket();mail_out.send(data_pack);

接收数据包

首先用DatagramSocket的另一个构造方法DatagramSocket(int port)创建一个对象,其中
的参数必须和待接收的数据包的端口号相同。例如,如果发送方发送的数据包的端口是5666,那么如下创建DatagramSocket对象:

DatagramSocket mail_in = new DatagramSocket(5666);

然后对象mail_in 使用方法receive (DatagramPacket pack)接收数据包。该方法有一个数据包参数pack,方法receive把收到的数据包传递给该参数。因此必须准备一个数据包以便收取数据包。这时需使用 DatagramPack类的另外一个构造方法DatagramPack (byte data[], int length)创建一个数据包,用于接收数据包,例如:

byte data[] = new byte[100];int length = 90;DatagramPacket pack = new DatagramPacket(data,length);mail_in.receive(pack);

该数据包pack将接收长度是length个字节的数据放入data。

注:

①receive方法可能会阻塞,直到收到数据包。

②如果pack调用方法getPort()可以获取所收数据包是从远程主机上的哪个端口发出的,即可以获取包的始发端口号;调用方法getLength()可以获取收到的数据的字节长度;调用方法InetAddress getAddress()可获取这个数据包来自哪个主机,即可以获取包的始发地址。我们称主机发出数据包使用的端口号为该包的始发端口号,发送数据包的主机地址称为数据包的始发地址。

③数据包数据的长度不要超过8192KB。

在下面的例子5中,张三和李四使用用户数据报(可用本地机器模拟)互相发送和接收数据包,程序运行时“张三”所在主机在命令行输入数据发送给“李四”所在主机,将接收到的数据显示在命令行的右侧;同样,“李四”所在主机在命令行输入数据发送给“张三”所在主机,将接收到的数据显示在命令行的右侧。程序代码如下所示:

①”张三”主机

import java.net.*;import java.util.Scanner;public class ZhangSan {  public static void main(String[] args) {    Scanner scanner = new Scanner(System.in);    Thread readData;    ReceiveLetterForZhang receiver = new ReceiveLetterForZhang();    try {      readData = new Thread(receiver);      readData.start(); //负责接收信息的线程      byte[] buffer = new byte[1];      InetAddress address = InetAddress.getByName("127.0.0.1");      DatagramPacket dataPack = new DatagramPacket(buffer,buffer.length, address, 666);      DatagramSocket postman=new DatagramSocket();      System.out.print("输入发送给李四的信息:");      while(scanner.hasNext()) {        String mess = scanner.nextLine();        buffer = mess.getBytes();        if (mess.length()==0)          System.exit(0);        buffer = mess.getBytes();        dataPack.setData(buffer);        postman.send(dataPack);        System.out.print("继续输入发送给李四的信息:");      }    }    catch(Exception e) {      System.out.println(e);    }  }}
import java.net.*;public class ReceiveLetterForZhang implements Runnable {  public void run() {    DatagramPacket pack = null;    DatagramSocket postman = null;    byte data[] = new byte[8192];    try {      pack = new DatagramPacket(data,data.length);      postman = new DatagramSocket(888);    }    catch (Exception e) {}    while (true) {      if (postman==null) break;      else        try {          postman.receive(pack);          String message = new String(pack.getData(),0,pack.getLength());          System.out.printf("%25s\n","收到:"+message);        }          catch (Exception e) {}    }  }}

②”李四”主机

import java.net.*;import java.util.Scanner;public class LiSi {  public static void main(String[] args) {    Scanner scanner = new Scanner(System.in);    Thread readData;    ReceiveLetterForLi receiver = new ReceiveLetterForLi();    try {      readData = new Thread(receiver);      readData.start(); //负责接收信息的线程      byte[] buffer = new byte[1];      InetAddress address = InetAddress.getByName("127.0.0.1");      DatagramPacket dataPack = new DatagramPacket(buffer,buffer.length, address, 888);      DatagramSocket postman=new DatagramSocket();      System.out.print("输入发送给张三的信息:");      while(scanner.hasNext()) {        String mess = scanner.nextLine();        buffer = mess.getBytes();        if (mess.length()==0)          System.exit(0);        buffer = mess.getBytes();        dataPack.setData(buffer);        postman.send(dataPack);        System.out.print("继续输入发送给张三的信息:");      }    }    catch(Exception e) {      System.out.println(e);    }  }}
import java.net.DatagramPacket;import java.net.DatagramSocket;public class ReceiveLetterForLi implements Runnable {  public void run() {    DatagramPacket pack = null;    DatagramSocket postman = null;    byte data[] = new byte[8192];    try {      pack = new DatagramPacket(data,data.length);      postman = new DatagramSocket(666);    }    catch (Exception e) {}    while (true) {      if (postman==null) break;      else        try {          postman.receive(pack);          String message = new String(pack.getData(),0,pack.getLength());          System.out.printf("%25s\n","收到:"+message);        }          catch (Exception e) {}    }  }}
a41308f797e11ba27a1887bc59415bb2.png 6a3ecb35ab9dc7a7036da4441760e834.png a41308f797e11ba27a1887bc59415bb2.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值