https://www.cnblogs.com/rogerroddick/archive/2009/08/31/1557228.html
https://www.cnblogs.com/rogerroddick/archive/2009/08/31/1557228.html
转载于:https://www.cnblogs.com/newworldnewstart/p/8450051.html
1、广播:
同一网段所有主机都能接收,前提是端口要监听
客户端发送广播,开启端口监听的服务端接收并打印消息
服务端程序:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TestServer {
public static void main(String[] args) {
int port = 9999;//开启监听的端口
DatagramSocket ds = null;
DatagramPacket dp = null;
byte[] buf = new byte[1024];//存储发来的消息
StringBuffer sbuf = new StringBuffer();
try {
//绑定端口的
ds = new DatagramSocket(port);
dp = new DatagramPacket(buf, buf.length);
System.out.println("监听广播端口打开:");
ds.receive(dp);
ds.close();
int i;
for(i=0;i<1024;i++){
if(buf[i] == 0){
break;
}
sbuf.append((char) buf[i]);
}
System.out.println("收到广播消息:" + sbuf.toString());
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
发送端程序:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Test {
public static void main(String[] args) {
// 广播的实现 :由客户端发出广播,服务器端接收
String host = "255.255.255.255";//广播地址
int port = 9999;//广播的目的端口
String message = "test";//用于发送的字符串
try {
InetAddress adds = InetAddress.getByName(host);
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(message.getBytes(),
message.length(), adds, port);
ds.send(dp);
ds.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、多播
多播数据报套接字类用于发送和接收 IP 多播包。MulticastSocket 是一种 (UDP) DatagramSocket,它具有加入 Internet 上其他多播主机的“组”的附加功能。
多播组通过 D 类 IP 地址和标准 UDP 端口号指定。D 类 IP 地址在 224.0.0.0 和 239.255.255.255 的范围内(包括两者)。地址 224.0.0.0 被保留,不应使用。
可以通过首先使用所需端口创建 MulticastSocket,然后调用 joinGroup(InetAddress groupAddr) 方法来加入多播组:(以上是jdk-doc的说明,补充如下:服务器和客户端必须都要加入相同的组播地址才可以)
服务器端程序:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
public class TestServer {
public static void main(String[] args){
//接受组播和发送组播的数据报服务都要把组播地址添加进来
String host = "225.0.0.1";//多播地址
int port = 9998;
int length = 1024;
byte[] buf = new byte[length];
MulticastSocket ms = null;
DatagramPacket dp = null;
StringBuffer sbuf = new StringBuffer();
try {
ms = new MulticastSocket(port);
dp = new DatagramPacket(buf, length);
//加入多播地址
InetAddress group = InetAddress.getByName(host);
ms.joinGroup(group);
System.out.println("监听多播端口打开:");
ms.receive(dp);
ms.close();
int i;
for(i=0;i<1024;i++){
if(buf[i] == 0){
break;
}
sbuf.append((char) buf[i]);
}
System.out.println("收到多播消息:" + sbuf.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端程序:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Test {
public static void main(String[] args){
String host = "225.0.0.1";//多播地址
int port = 9998;
String message = "test-multicastSocket";
try {
InetAddress group = InetAddress.getByName(host);
MulticastSocket s = new MulticastSocket();
//加入多播组
s.joinGroup(group);
DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(),group,port);
s.send(dp);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
简单实现了一下基于UDP的广播和多播的功能,主要是理解多播和广播的概念。尤其是组播,以前停留在概念上,只知道是传送给一组主机而不是所有主机,今天才豁然了。
欢迎转载,但请引用本文链接。
来源:oschina
链接:https://my.oschina.net/u/1390988/blog/213757
广播和多播仅用于UDP,应用于多个接受者的情况,TCP源目一定是单播,某两个主机之间建立连接,不支持广播和多播。
广播一个主机向网上所有其他主机发送帧如ARP,多播传送给属于多播组的多个主机。
从物理网络提取数据包到接口卡(物理层):通常网卡接收那些目的地址为网卡物理地址或广播组播地址的帧。接口卡主要处理检验和,比如小于最小长度坏包,检验和错了,接口卡就直接丢弃。
物理层到设备驱动程序(链路层):帧的类型必须要有三层协议位(IP,ARP等),进行多播过滤来检验有无上层信息(IP头部)或该主机是否属于多播地址,多播地址有相对应的mac地址和多播组mac地址是否相同,从物理到二层不是想收的多播就过滤了,但是广播会继续往上传。
数据链路层到IP:基于IP地址访问控制列表过滤,广播会继续往上传。
IP到UDP:由IP传送来的数据报,就根据端口号,有时还有源端口号(有无上层应用程序监控)进行数据报过滤。如果没有进程使用该目的端口号,就丢弃该数据包并产生ICMP不可达报文,没有上层应用程序的广播在此过滤。
广播出来所有的主机都会从物理层到UDP提交时才检测,非常消耗资源。
组播在链路层就被检测过滤,所以组播比广播好。
多播组地址包括为1110的最高四个bit和多播组号。它们通常可表示为点分十进制数,范围从224.0.0.0到239.255.255.255.
多播对应的以太网地址范围从01:00:5e:00:00:00到01:00:5e:7f:ff:ff。如多播IP地址224.128.64.32(十六进制e0.80.40.20)和224.0.64.32(十六进制e0.80.40.20)都映射为同一以太网地址01:00:5e:00:40:20。多播数据要经过数据链路层进行mac地址绑定后进行发送,所以一个以太网卡在绑定一个多播IP地址后,还要绑定一个多播mac地址,多播IP和多播mac不是一一对应的,那么主机设备驱动和IP层就必须对数据报过滤。 IP地址虚线的部分映射到mac地址,一个mac对应多个组播地址。DNS
访问网站不要输入IP地址,把主机名和IP地址之间的转换,DNS提供了允许客户端和服务器相互通信的协议,对DNS的访问通过地址解析器(resolver) 完成。DNS是应用程序,操作系统内核的TCP/IP协议簇对DNS一点都不知道。
要用TCP/IP必须给IP地址,所以用DNS把名字IP地址解析出来。
DNS的名字空间和Unix的文件系统类似,也具有层次结构,命名树上任何一个节点的域名就是将该节点同最高层的域名串连,中间使用“.”分隔这些域名。
当一个新系统加入到一个区域中时,该区域的DNS管理者为该系统申请一个域名和一个IP地址,并将它们加入到名字服务器的数据库中。
客户程序防火墙通过标识出去的UDP的包确定相应和查询是否匹配。
紧接着的16个bit又可以做进一步的划分,标识了报文的性质,比如说查询还是响应报文,需要递归与否。AA:授权服务器回答,高速缓存非授权。
RD:期望递归,期望服务器做递归查询
查询问题后有查询类型,包括A,NS,CNAME,PTR,HINFO,MX。
响应报文可以回复多个IP,域名可以和多个IP地址对应。
正向查询是通过域名获得IP的查询,但反向查询时通过IP获得域名。例如host命令,host domain就可获得对应服务器ip。host ip获得域名。
在DNS正向查询里做反向查询需要遍历整个数据库,开销较大,DNS使用另一颗子树维护IP---域名对应表,这个子树的根节点是in-addr.arpa,对于IP地址为140.252.13.33的主机,它的DNS名字为33.13.252.140.in-addr.arpa。在DNS系统一个反向地址对应一个PTR记录。
DNS高速缓存
第一次服务器解析,第二次在高速缓存找结果,以加快查询速度。
是UDP还是TCP
两个服务器之间做域传送,因为数据量大TCP传送效率高些,除此以外一般用UDP,53号端口。
TFTP简单文件传输协议
TFTP代码小适合在只读存储器中使用,比如路由器ROM基本的操作系统。发送每块数据都是停止等待对方的确认,每次最多发512字节,发完后每块后等待回应发新的,等不到超时重传。
我有一个嵌入式设备(源),它通过UDP数据包以20毫秒(=约330字节)的块发送(音频)数据流 . 因此,网络容量相当低,约为16kBps(实际上由于UDP / IP开销而略多) . 设备运行lwIP堆栈(v1.3.2)并使用H&D Wireless的WiFi解决方案(HDG104,WiFi G模式)连接到WiFi网络 . 目的地(接收器)是Windows Vista PC,它也使用USB WiFi加密狗(WiFi G模式)连接到WiFi网络 . PC上运行的程序允许我监视丢弃的数据包的数量 . 我也在运行Wireshark来直接分析网络流量 . 此时,没有其他客户端通过网络主动发送数据 .
当我使用广播或多播发送数据时,许多数据包被丢弃,有时高达15% . 但是,当我切换到使用UDP单播时,丢弃的数据包数量可以忽略不计(<2%) .
使用UDP我希望丢弃数据包(在我的音频应用程序中这是正常的),但为什么我看到广播/多播和单播之间的性能有如此大的差异?
我的路由器是WRT54GS(FW v7.50.2),PC(接收器)使用的是Trendnet TEW-648UB网络适配器,在WiFi G模式下运行 .