DatagramPacket类
DatagramPacket表示数据报,它的构造方法分为两类:一类构造方法创建DatagramPacket对象用来
接受数据,还有一类构造方法创建的Data,还有一类构造方法创建的DatagramPacket对象用来发送
数据。用于发送数据的构造方法需要设定数据报到达的目的地址。(一般是客户端需要设置)
接收数据报的构造方法:
public DatagramPacket(byte[]data,int length)
public DatagramPacket(byte[]data,int offset,int length)
注:length接收的字节数,offset是从哪个字节开始接收。默认是data[0];
用于发送数据的构造方法:
public DatagramPacket(byte[] data,int offset,int length,InetAddress address,int
port)
public DatagramPacket(byte[] data,int offset,int length,SocketAddress address)
public DatagramPacket(byte[] data,int length,InetAddress address,int prot)
public DatagramPacket(byte[] data,int length,SokcetAddress address)
注:length指定要发送的字节数,参数offset指定要发送的数据在data中的起始位置。
--------
数据报的大小
DatagramPacket的构造方法有一个参数length,它决定了要接收或发送数据报的长度。对于用于接
收数据的DatagramPacket,如果实际接收到的数据报的长度大于DatagramPacket,如果实际接收到的
数据报的长度大于DatagramPacket的最大长度,那么多余的数据就会被丢弃。IPv4数据报的最大长
度65507字节;IPv6最大长度是65536字节。
实际上,许多基于UDP的协议,如DNS和TFTP,都规定数据报的长度不超过512字节。基于UDP协议的
NFS协议则允许数据报的最大长度8192字节。多数网络系统实际上并支持长度大于8192字节(8kb)的
数据报。
注:一个完整的UDP数据报包括IP头,UDP头和数据这3部分。UDP头部分包括源端口与目标端口号。
-------
DatagramPacket的属性
data:数据报的缓冲区
offset:数据报的数据缓冲区的其实位置
length:数据报的长度
address:对于用于发送数据报,address表示数据报的目标地址。对于接收数据报,address表示发
送者的地址。
port:端口
---------
数据格式的转换
数据报只能存放字节形式的数据。
发送方需要将其他格式的数据转换为字节序列。在接收方需要把字节序列转换为原来格式的数据。
----------
DatagramSocket类
DatagramSocket负责接收和发送数据报。在客户程序,一般由操作系统为DatagramSocket分配端口
(匿名端口)。在服务程序中,一般由程序显式地为DatagramSoc分别端口。

几种构造方法
DatagramSocket()
DatagramSocket(int port)
DatagramSocket(int port,InetAddress address)
DatagramSocket(SocketAddress bindaddr)
--------------
管理连接
两个TCP Socket之间存在固定的连接关系,而一个DatagramSocket可以与其他任何一个
DatagramSocket交换数据报。
--------
DatagramChannel类:
使用DataChannel,可以使得UDP服务器只需用单个线程就能同时与多个客户通信。默认情况下是采
用阻塞模式,采用非阻塞模式,需要调用configureBlocking(boolean b)方法。
创建DatagramChannel
每一个DatagramChannel对象都关联了一个DatagramSocket对象。
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
SocketAddress address = new InetAddress(8088);
socket.bind(address);
---------
组播Socket
网络数据传播按照接收者的数量,可分为以下3种方式:
单播:提供点对点的通信。发送者每次发送的数据有着唯一的目的地址,只被一个接收者接收。
广播:发送者每次发送的数据可以被传播范围内的所有接收者接收。
组播:发送者每次发送的数据可以被小组内的所有接收。
大多数组播数据为音频或视频,这些数据一般很大,如果部分数据在传输途中丢失,接收方也可以
识别信号。因此组播数据通过UDP发送,虽然不可靠,但比面向连接的TCP的传输速度快3倍
以上。
----------
MulticastSocket类
java.net.MulticastSocket具有组播的功能,它是DatagramSocket的子类
MulticastSocket ms = new MulticastSocket(null),//不与任何本地端口绑定,需要调用bind
(port)方法绑定端口
ms.setResuseAddress(false);//设置MulticastSocket的SO_REUSEADDR选项
SocketAddress address = new InetSocketAddress(4000);
ms.bind(address);
与组播通信:
加入到组播组:joinGroup()方法:
向组中成员发送数据报:send()方法
接收发送到组播组的数据报:receive()方法
离开组播组:leaveGroup()方法。

**
 * 组播的发送方
 *发送方将数据发送到224.0.0.1:4000上面
 *接收方从224.0.0.1:4000上去数据;
 *消息队列跟这个差不多
 */
public class MulticastSender {

    public static void main(String[] args) throws Exception {
        InetAddress group = InetAddress.getByName("224.0.0.1");
        int port = 4000;
        MulticastSocket ms = null;
        
        try {
            ms = new MulticastSocket(port);
            ms.joinGroup(group);//加入组播
            while(true){
                String message = "hello" + new Date();
                byte[] buffer = message.getBytes();
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, port);
                ms.send(packet);//发送数据
                System.out.println("发送数据报给:" +group+":"+port);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(ms != null){
                ms.leaveGroup(group);
                ms.close();
            }
        }
    }    
}
public class MulticastReceive {

    public static void main(String[] args) throws Exception {
        InetAddress group = InetAddress.getByName("224.0.0.1");
        int port = 4000;
        MulticastSocket ms = null;
        
        try{
            ms = new MulticastSocket(port);
            ms.joinGroup(group);
            
            byte[] buffer = new byte[8192];
            while(true){
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                ms.receive(packet);
                String string = new String(packet.getData(), 0, packet.getLength());
                System.out.println(string);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(ms != null){
                ms.leaveGroup(group);
                ms.close();
            }
        }
    }

}

 

posted on 2019-05-01 20:41  lazyli  阅读(1178)  评论(0编辑  收藏  举报