您的位置:首页 > 理论基础 > 计算机网络

java网络编程(四)

2016-12-17 18:45 267 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: