java网络编程(四)

TCP是为数据的可靠传输而设计的,如果数据在传输中丢失或损坏,TCP会保证再次发送数据。如果数据包乱序到达,TCP会将其置回正确的顺序。

这个可靠性的代价就是速度,建立和撤销TCP连接会花费较长的时间。


用户数据报协议UDP是在IP之上发送数据的另一种传输层协议,速度快,但不可靠。

可以通过UDP实现一个可靠的文件传输,只是由应用程序负责可靠性,UDP不关心这一点。


java中UDP的实现分为两个类:DatagramPacket和DatagramSocket

DatagramPacket将数据字节填充到UDP包中,称为数据报。

DatagramSocket可以收发UDP数据报,发送数据时,要将数据放入DatagramPacket中,然后使用DatagramSocket将其发送;

接收数据时,可以从DatagramSocket中接收一个DatagramPacket对象。


在UDP中,关于数据报的所有信息(包括发送的目标地址)都包含在Packet中。

UDP没有两台主机间唯一连接的概念,一个socket会收发所有指向指定端口的数据,而不需要知道对方是谁。



UDP客户端:

//UDP客户端指定端口0,就是随机选择一个可用端口
DatagramSocket socket = new DatagramSocket(0);
socket.setSoTimeout(10000);
InetAddress host = InetAddress.getByName("time.nist.gov");

//发送的数据报,指出要连接的远程主机和端口
DatagramPacket request = new DatagramPacket(new byte[1], 1, host, 13);
//接收的数据报要足够大
DatagramPacket response = new DatagramPacket(new byte[1024], 1024);
socket.send(request);
socket.receive(response);
String result = new String(response.getData(), 0, response.getLength(), "US-ASCII");


UDP服务端

//服务器端监听13端口
DatagramSocket socket = new DatagramSocket(13);
while(true) {
try {
DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
//会无限阻塞,直到一个UDP数据报到达端口13
socket.receive(request);

String daytime = new Date().toString();
byte[] data = daytime.getBytes("US-ASCII");
//发送回的数据包括请求的客户端的IP和客户端的端口
DatagramPacket response = new DatagramPacket(data, data.length, request.getAddress(), request.getPort());
socket.send(response);
}catch (IOException ex) {

}
}

socket.close();


许多Internet协议同时有TCP和UDP实现,当主机接收到一个IP包时,主机会检查IP首部来确定它是TCP数据包还是UDP数据报。

根据约定,若同一个服务同时有TCP、UDP实现,就使用相同的端口号。



DatagramChannel类

//基于通道的服务端的UDP
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
SocketAddress address = new InetSocketAddress(9);
socket.bind(address);
ByteBuffer buffer = ByteBuffer.allocate(65507);
while(true) {
//若通道是阻塞的,则这个方法一直等待;若通道是非阻塞的,则没有包可读的情况下,立即返回null
SocketAddress client = channel.receive(buffer);
buffer.flip();
while(buffer.hasRemaining()) {
System.out.println(buffer.get());
}
buffer.clear();
}


通道通过configureBlocking(false)可设置非阻塞状态



IP组播:

初始的路由器只向靠近接收主机的路由器发送一份消息副本,然后这个路由器建立多个副本,发送给位于目的地或更靠近目的地的不同接收方。

Internet组播建立在UDP基础上。


组播设计尽可能无缝地用于Internet,大多数工作都是由路由器完成,对于应用程序员应当是透明的。应用程序只是将数据包发送给一个组播地址,它在功能上于任何其他IP地址没有区别。路由器将确保包被分发到该组播组中所有主机。


组播地址是称为组播组的一组主机的共享地址。任何发送给该组播地址的数据都会中继给组中的所有成员。组播组中的成员是开放的,主机可以在任何时候进入或离开组。

组可以是永久的,也可以是临时的。要创建一个新的组播组,就是在225.0.0.0到238.255.255.255之间随机选择一个地址,为该地址创建一个InetAddress对象,开始向它发送数据。


注意数据报中的TTL值,TTL是允许数据报经过的最大路由器数目,当达到这个最大值时,就会将这个包丢弃。

从程序员的角度看,组播和UDP的主要区别就是,你必须考虑TTL,这是IP首部中一个1到255的一个字节的数.

TTL字段最初是为了防止路由循环而设计的,以保证所有包最终都会被丢弃。


是否支持组播:

需要你的主机和远程主机之间必须有一个由组播路由器构成的路径,或者有些网站可能连接着特殊的组播隧道软件,可以通过所有路由器都理解的单播UDP传播组播数据。


向组播地址发送数据与向单播地址发送UDP数据很相似,不需要加入组播组就可以向组播地址发送数据。

从组播组接收数据就必须加入组播组了。


//组播监听器
InetAddress group = InetAddress.getByName("239.255.255.250");
int port = 1900;
MulticastSocket ms = new MulticastSocket(port);
ms.joinGroup(group);
byte[] buffer = new byte[8192];
while(true) {
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ms.receive(dp);
String s = new String(dp.getData(), "8859_1");
}



leaveGroup(组)用来离开组播组

setTimeToLive(数字)在向组播组发送数据时,用来设置TTL



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值