`
outlaw
  • 浏览: 29778 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

数据报(UDP)信道

阅读更多

数据报(UDP)信道

http://book.51cto.com/art/200902/109761.htm

  • 摘要:《Java TCP/IP Socket编程》第5章NIO,本章将对"New I/O"工具包的主要应用进行介绍。NIO主要包括两个部分:java.nio.channels包介绍了Selector和Channel抽象,java.nio包介绍了Buffer抽象。本节为大家介绍数据报(UDP)信道。
  • 标签:UDP  Java  TCP  IP  Socket  编程
  • JavaNIO包通过DatagramChannel类实现了数据报(UDP)信道。与我们之前看到的其他形式的SelectableChannel一样,DatagramChannelDatagramSocket上添加了选择和非阻塞行为,以及基于缓冲区的I/O操作能力。

    DatagramChannel: 创建,连接和关闭

    static DatagramChannel open()
    boolean isOpen()
    DatagramSocket socket() void close()

    需要调用DatagramChannelopen()工厂方法来创建一个DatagramChannel实例,该实例是未绑定的。DatagramChannel只是对基本DatagramSocket的一个包装器(wrapper)。使用其socket()方法可以直接访问内部的DatagramSocket实例。这就允许通过调用基本的DatagramSocket方法进行绑定、设置套接字选项等操作。用完DatagramChannel后,要调用它的close()方法将其关闭。

    只要创建了一个DatagramChannel实例,就可以非常直接地发送和接收数据。

    DatagramChannel: 发送和接收

    int send(ByteBuffer src, SocketAddress target)
    SocketAddress receive(ByteBuffer dst)

    send()方法用于创建一个包含了给定ByteBuffer中的数据的数据报文,并将其发送到目的地址指定的SocketAddress上。receive()方法用于将接收到的数据报文存入指定缓冲区并返回发送者的地址。重要提示:如果缓冲区的剩余空间小于数据报文中的数据大小,多余的数据将毫无提示地丢弃。

    以下代码段用于创建一个DatagramChannel实例,并将UTF-16编码的字符串"Hello"发送到运行在同一主机的5000端口上的UDP服务器上。

    DatagramChannel channel = DatagramChannel.open();
    ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes("UTF-16"));
    channel.send(buffer, new InetSocketAddress("localhost", 5000));

    以下代码段用于创建一个DatagramChannel实例,将底层的套接字绑定到5000端口,接收最长为20字节的数据报文,并将字节转换成使用UTF-16编码的字符串。

    DatagramChannel channel = DatagramChannel.open();
    channel.socket().bind(new InetSocketAddress(5000));
    ByteBuffer buffer = ByteBuffer.allocateDirect(20);
    SocketAddress address = channel.receive(buffer);
    buffer.flip();
    String received = Charset.forName("UTF-16").
    newDecoder().decode(buffer).toString();

    在上面的send()实例中,调用send()方法时并没有显式地绑定本地端口,因此将随机选择一个可用端口。相应的receive()方法用于返回一个SocketAddress,其中包含了端口号。

    如果总是向同一个远程终端发送或接收数据,我们可以选择调用connect()方法,并使用 SocketAddress指定远程终端的地址。

    DatagramChannel: 连接DatagramChannel

    DatagramChannel connect(SocketAddress remote)
    DatagramChannel disconnect()
    boolean isConnected()
    int read(ByteBuffer dst)
    long read(ByteBuffer[] dsts)
    long read(ByteBuffer[] dsts, int offset, int length)
    int write(ByteBuffer src)
    long write(ByteBuffer[] srcs)
    long write(ByteBuffer[] srcs, int offset, int length)

    这些方法限制我们只能通过指定的地址发送和接收数据。为什么要这样做呢?原因之一是调用connect()方法后,可以使用read()write()方法来代替receive()send()方法,并且不需要处理远程地址。read()write()方法分别用于接收和发送一个数据报文。分散式读操作以一个ByteBuffer数组为参数,只接收一个数据报文,并按顺序将其填入缓冲区中。聚集式写操作将缓冲区数组中的所有字节连接起来创建一个要传输的数据报文。重要提示:现在能够发送的最大数据报文可以包含65507个字节,试图发送更多的数据将被无提示地截断。

    使用connect()方法的另一个好处是,已建立连接的数据报文信道可能只接收从指定终端发送来的数据,因此我们不需要测试接收端的有效性。注意,DatagramChannelconnect()方法只起到限制发送和接收终端的作用,连接时并没有数据包在SocketChannel上进行交换,而且也不需要像SocketChannel那样等待或测试连接是否完成。(见第6章)

    到目前为止DatagramChannel看起来与DatagramSocket非常相似。数据报文信道和套接字的主要区别是,信道可以进行非阻塞I/O操作和使用选择器。DatagramChannel中选择器的创建,信道的注册、选择等,与SocketChannel几乎一模一样。有一个区别是DatagramChannel不能注册连接I/O操作,不过也不需要这样做,因为DatagramChannelconnect()方法永远不会阻塞。

    DatagramChannel: 设置阻塞行为和使用选择器

    SelectableChannel configureBlocking(boolean block)
    boolean isBlocking()
    SelectionKey register(Selector sel, int ops)
    SelectionKey register(Selector sel, int ops, Object attachment)
    boolean isRegistered()
    int validOps()
    SelectionKey keyFor(Selector sel)

    这些方法的功能与SocketChannelServerSocketChannel中的相应方法一样。

    下面使用DatagramChannel对第4章中的DatagramSocket UDP回显服务器进行重写。服务器侦听指定的端口,并将接收到的数据报文简单地回发给客户端。重写后的服务器与原来版本的主要区别是它不会在send()receive()方法上阻塞等待。

    UDPEchoServerSelector.java

    0 import java.io.IOException;
    1 import java.net.InetSocketAddress;
    2 import java.net.SocketAddress;
    3 import java.nio.ByteBuffer;
    4 import java.nio.channels.DatagramChannel;
    5 import java.nio.channels.SelectionKey;
    6 import java.nio.channels.Selector;
    7 import java.util.Iterator;
    8
    9 public class UDPEchoServerSelector {
    10
    11 private static final int TIMEOUT = 3000; // Wait timeout (milliseconds)
    12
    13 private static final int ECHOMAX = 255; // Maximum size of echo datagram
    14
    15 public static void main(String[] args) throws IOException {
    16
    17 if (args.length != 1) // Test for correct argument list
    18 throw new IllegalArgumentException("Parameter(s): <Port>");
    19
    20 int servPort = Integer.parseInt(args[0]);
    21
    22 // Create a selector to multiplex client connections.
    23 Selector selector = Selector.open();
    24
    25 DatagramChannel channel = DatagramChannel.open();
    26 channel.configureBlocking(false);
    27 channel.socket().bind(new InetSocketAddress(servPort));
    28 channel.register(selector, SelectionKey.OP_READ, new ClientRecord());
    29
    30 while (true) { // Run forever, receiving and echoing datagrams
    31 // Wait for task or until timeout expires
    32 if (selector.select(TIMEOUT) == 0) {
    33 System.out.print(".");
    34 continue;
    35 }
    36
    37 // Get iterator on set of keys with I/O to process
    38 Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
    39 while (keyIter.hasNext()) {
    40 SelectionKey key = keyIter.next(); // Key is bit mask
    41
    42 // Client socket channel has pending data?
    43 if (key.isReadable())
    44 handleRead(key);
    45
    46 // Client socket channel is available for writing and
    47 // key is valid (i.e., channel not closed).
    48 if (key.isValid() && key.isWritable())
    49 handleWrite(key);
    50
    51 keyIter.remove();
    52 }
    53 }
    54 }
    55
    56 public static void handleRead(SelectionKey key) throws IOException {
    57 DatagramChannel channel = (DatagramChannel) key.channel();
    58 ClientRecord clntRec = (ClientRecord) key.attachment();
    59 clntRec.buffer.clear(); // Prepare buffer for receiving
    60 clntRec.clientAddress = channel.receive(clntRec.buffer);
    61 if (clntRec.clientAddress != null) { // Did we receive something?
    62 // Register write with the selector
    63 key.interestOps(SelectionKey.OP_WRITE);
    64 }
    65 }
    66
    67 public static void handleWrite(SelectionKey key) throws IOException {
    68 DatagramChannel channel = (DatagramChannel) key.channel();
    69 ClientRecord clntRec = (ClientRecord) key.attachment();
    70 clntRec.buffer.flip(); // Prepare buffer for sending
    71 int bytesSent = channel.send(clntRec.buffer, clntRec.clientAddress);
    72 if (bytesSent != 0) { // Buffer completely written?
    73 // No longer interested in writes
    74 key.interestOps(SelectionKey.OP_READ);
    75 }
    76 }
    77
    78 static class ClientRecord {
    79 public SocketAddress clientAddress;
    80 public ByteBuffer buffer = ByteBuffer.allocate(ECHOMAX);
    81 }
    82 }

    UDPEchoServerSelector.java

    分享到:
    评论

    相关推荐

      02UDP通信程序1

      UDP(User Datagram Protocol)协议是“用户数据报协议”,它是一种无连接的协议,当计算机利用 UDP 协议进行数据传输的时候,发送方只需设置目标 IP 地址和端口号就可以发送数据,连接操作在 UDP 通信中是无意义的...

      杭州电子科技大学研究生考卷(附答案)

      IP 数据报要经过互连网中许多路由器的存储转发,但 UDP 用户数据报是在运输层的端到端抽象的逻辑信道中传送的。 TCP 报文段是在运输层抽象的端到端逻辑信道中传送,这种信道是可靠的全双工信道。但这样的信道却不...

      流媒体数据传输主动式滤波整流模型

      大量的客户端反馈, 致使带宽调整具有较大的滞后性而不适合基于UDP 的VBR 流媒体服务的问题, 提出了一种 基于流媒体数据传输速率本身特征的主动滤波整流模型。由于此模型无需客户反馈信息, 可利用服务器的数据缓 冲对...

      4计算机网络复习题.doc

      8.OSPF不用 UDP 数据报而是直接用IP数据报传送,其IP数据报首部的协议字段值为 89 。 9.在OSPF路由协议中,需要通过呼叫协议在网络中选举 指定 路由器和 备份指定 路由器,其它路由器将与它们建立邻接关系以交换...

      数据通信与计算机网络作业答案Word版.doc

      4) 数据链路层:发送方,将网络层传来的IP数据报组装成帧,并在两个相邻节点间的链路 上传送以帧为单位的数据;接收方,根据控制信息从帧中提取出数据交给网络层。 5) 物理层:透明传送比特流。所传送数据的单位是...

      计算机网络复习题

      UDP(User Datagram Protocol -1分,用户数据报协议-1分):无连接的、面向报文的、尽最大努力交付的(不保证可靠)、没有拥塞控制的、首部开销小(1分) TCP(Transmission Control Protocol-1分, 传输控制协议-1分...

      计算机网络考研期末知识点总结

      2.IP数据报 3.IP地址 4.地址解析协议ARP 5.网际控制报文协议ICMP 6.网络地址转换NAT 7.IPv6 8.路由选择协议 9.路由器 10.路由表与转发表 第五章传输层 1.传输层的功能 2.传输层常用端口号 3.面向连接与无连接 4.UDP...

      计算机网络&计算机网络

      4.1.1 虚电路和数据报 4.1.2 两者比较 4.2 广域网实例 4.2.1 PSTN 4.2.2 X.25 4.2.3 DDN 4.2.4 帧中继 4.2.5 SMDS 4.2.6 B-ISDN/ATM 4.3 各种广域网的比较 4.4 小结 习题 第5章 局域网 5.1 介质访问控制...

      计算机网络(汲及内容全面)

      4.1.1 虚电路和数据报 4.1.2 两者比较 4.2 广域网实例 4.2.1 PSTN 4.2.2 X.25 4.2.3 DDN 4.2.4 帧中继 4.2.5 SMDS 4.2.6 B-ISDN/ATM 4.3 各种广域网的比较 4.4 小结 习题 第5章 局域网 5.1 介质访问控制...

      计算机网络基础知识

      4.1.1 虚电路和数据报 4.1.2 两者比较 4.2 广域网实例 4.2.1 PSTN 4.2.2 X.25 4.2.3 DDN 4.2.4 帧中继 4.2.5 SMDS 4.2.6 B-ISDN/ATM 4.3 各种广域网的比较 4.4 小结 习题 第5章 局域网 5.1 介质访问...

      经典全面系统的网络工程师资料

      4.1.1 虚电路和数据报 4.1.2 两者比较 4.2 广域网实例 4.2.1 PSTN 4.2.2 X.25 4.2.3 DDN 4.2.4 帧中继 4.2.5 SMDS 4.2.6 B-ISDN/ATM 4.3 各种广域网的比较 4.4 小结 习题 第5章 局域网 5.1 介质访问控制...

      吉林大学计算机网络期末试卷

      5.1分组交换技术(虚电路、面向连接、数据报) 5.2逆向自学习(校园网) 不能有环 D-V 外部网关协议 L-S 内部网关协议 5.3 IP协议: IP分组的格式、IP地址、字段含义 5.4子网划分 第六章: 6.1传输地址 6.2 TCP三...

      进程间通讯Demo.zip

      为了满足不同程序对通信质量和性能的要求,一般的网络系统都提供了流式、数据报式、原始3种不同类型的套接字。 Socket通信方式: 同步:客户端在发送请求之后必须等到服务器回应之后才可以发送下一条请求——串行...

      计算机第五次作业网络.docx

      选择一项: 传输控制协议 超文本传输协议 用户数据报协议 文件传输协议 反馈正确答案是:用户数据报协议 题目 20 以下不属于目前常用的传输介质的是 。 选择一项: 同轴电缆 光纤 双绞线 卫星信道 反馈正确答案是:...

      《计算机网络安全与应用》习题答案.doc

      例如,电话通 信系统中的非对称数据用户环路ADSL是一个面向连接的服务,在此传输信道上也可以封 装传输无连接的IP数据报。 10.答:此题的分析方法参看教材21页例1- 4。从计算机A产生的发送给计算机D的IP包中,源IP...

      Java CP/IP Socket编程

      5.7 数据报(UDP)信道..........144 5.8 练习..........149 1. 使用定长的写缓冲区改写TCPEchoClientNonblocking.java。..........149 2.使用Buffer和DatagramChannel编写一个回显客户端。..........149 第6章...

      远驱240控制器调整参数-智能控制器.pdf

      ⽀持蓝⽛通信功能,结合⼿机APP,可实现RTU的参 数查询与设置,历史数据查询,图像抓拍,测试报和⼈⼯置数编报触发等。 ⾃带GPRS通信功能,⽀持GPRS/GSM通信模式:⽀持GSM/GPRS;实际带宽不⼩于 20-50Kb/s;数据速率 ...

      清华大学的计算机网络课件

      但又常说“路由器转发IP数据报”或“路由器转发帧”。究竟“分组”一词应当用在什么场合? 问题1-9:到商店购买可一个希捷公司生产的80 G的硬盘。安装到电脑上以后用WINDOWS的资源管理器发现在该磁盘的“属性”中...

    Global site tag (gtag.js) - Google Analytics