单播 单播(原文:unicast)是指数据包在计算机网络的传输中,目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如一切基于TCP的协议。
组播 多播(英语:multicast,台湾又译作多点发送、多点广播或群播,中国大陆又译作组播)是指把信息同时传递给一组目的地址。它使用的策略是最高效的,因为消息在每条网络链路上只需传递一次,且只有在链路分叉的时候,消息才会被复制。
广播 广播(英语:broadcast)是指将信息数据包发往指定网络范围内的所有设备[1]。其发送范围称为“广播域”。
并非所有的计算机网络都支持广播,例如X.25网络和帧中继都不支持广播,而且也没有在“整个互联网范围中”的广播。IPv6亦不支持广播,广播的相应功能由多播代替。
通常来说,广播都是限制在局域网范围内,比如以太网或令牌环网络。因为广播在广域网中可能造成比在局域网中大的多的影响。
UDP 是什么 udp 是用户数据报文协议 特点:
UDP 包的最大长度: 16 位 -> 2字节 2^16 - 1 = 65536 - 1 = 65535 字节长度 自身协议占用32 + 32 = 64 位 = 8字节 65536 - IP头长度(20)- 8 = 65507 (理论)
java 中Udp相关api
DatagramSocket 创建简单的实例,指定端口时,创建监听指定端口的实例。
DatagramPacket packet 用于将byte数组包装为报文,或者将报文拆分为byte数组。
构造函数 DatagramPacket(bytes[], length, InetAddress, port) 依次为数据的byte数组,byte数组的长度,要传输的地址,要传输的端口号
packet getAddress 发送者的地址
packet getAddress().getHostAddress() 获取发送者的IP地址
packet getPort() 获取发送者的端口
packet getLength() 获取接收到的数据长度
packet getData() 获取接收到的数据
receive(DatagramPacket d) 接收数据
send(DatagramPacket d) 发送数据
java upd 实现单播 服务端监听20000端口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class UdpServer { public static void main (String[] args) { System.out.println("UDPServer started." ); DatagramSocket ds = new DatagramSocket(20000 ); final byte [] buf = new byte [512 ]; DatagramPacket receivePackt = new DatagramPacket(buf, buf.length); ds.receive(); String ip = receivePackt.getAddress().getHostAddress(); int port = receivePackt.getPort(); int dataLen = receivePackt.getLength(); String data = new String(receivePackt.getData, 0 , dataLen); System.out.println("UDPServer receive from ip: " + ip + "\t port:" + port + "\tdata:" + data ); String responseData = "Receive data with len: " + dataLen; byte [] responseDataBytes = responseData.getBytes(); DatagramPacket responsePacket = new DatagramPacket( responseDataBytes, responseDataBytes.length, receivePackt.getAddress(), receivePackt.getPort() ); ds.send(responsePacket); System.out.println(" UDPServer finished" ); ds.close(); } }
客户端向20000端口发送信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class UdpClient { public static void main (String[] args) { System.out.println(" UdpClient start" ); DatagramSocket ds = new Datagramsocket(); String requestData = "Hello World" ; byte [] requestBytes = requestData.getBytes(); DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length); requestPacket.setAddress(Inet4Address.getLocalHost()); requestPacket.setPort(20000 ); ds.send(requestPacket); final byte [] buf = new byte [512 ]; DatagramPacket receivePacket = new DatagramPacket(byte , byte .length); ds.receive(receivePacket); String ip = receivePack.getAddress().getHostAddress(); int port = receivePack.getPort(); int dataLen = receivePack.getLength(); String data = new String(receivePack.getData(), 0 , dataLen); System.out.println("UDPSearcher receive from ip: " + ip + "\t port:" + port + "\tdata:" + data ); System.out.println(" UDPSearcher finished" ); ds.close(); } }
java upd 广播 实现思路: A -> B 、C 、D 数据流向: A 监听30000 端口,B,C,D监听20000端口 , A 向20000 端口发送广播后,B、C、D接收到消息(消息中含有需要回复的端口号)后,向30000端口进行回复。
服务端监听20000端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public class Server { public static void main (String[] args) throws IOException { String sn = UUID.randomUUID().toString(); Send send = new Send(sn); send.start(); System.in.read(); send.exit(); } private static class Send extends Thread { private final String sn; private boolean done = false ; private DatagramSocket ds = null ; public Provider (String sn) { this .sn = sn; } @Override public void run () { System.out.println("UDPProvider started." ); try { ds = new DatagramSocket(20000 ); while (!done) { final byte [] buf = new byte [512 ]; DatagramPacket receivePacket = new DatagramPacket(buf, buf.length); ds.receive(receivePacket); String ip = receivePack.getAddress().getHostAddress(); int port = receivePack.getPort(); int dataLen = receivePack.getLength(); String data = new String(receivePack.getData(), 0 , dataLen); System.out.println("UDPProvider receive from ip: " + ip + "\t port:" + port + "\tdata:" + data); int responsePort = MessageCreator.parsePort(data); if (responsePort != -1 ) { String responseData = MessageCreator.buildWithSn(sn); byte [] responseDataBytes = responseData.getBytes(); DatagramPacket responsePacket = new DatagramPacket(responseDataBytes, responseDataBytes.length, receivePack.getAddress(), responsePort); ds.send(responsePacket); } } } catch (Exception ignore) { } finally { close(); } System.out.println(" UDPProvider finished" ); } private void close () { if (ds != null ) { ds.close(); ds = null ; } } void exit () { done = true ; close(); } } }
口令的创建与解析 根据口令对client信息中的端口号进行解析1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class MessageCreator { private static final String SN_HEADER = "收到暗号,我是(SN) :" ; private static final String PORT_HEADER = "这是暗号,请回电端口(port):" ; public static String buildWithPort (int port) { return PORT_HEADER + port; } public static int parsePort (String data) { if (data.startsWith(PORT_HEADER)) { return Integer.parseInt(data.substring(PORT_HEADER.length())); } return -1 ; } public static String buildWithSn (String sn) { return SN_HEADER + sn; } public static String parseSn (String data) { if (data.startsWith(SN_HEADER)) { return data.substring(SN_HEADER.length()); } return null ; } }
udp广播的Client
监听A、B、C的回拨端口30000,后向A、B、C端口发送信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 class Client { private static final int LISTEN_PORT = 30000 ; public static void main (String[] args) { Listener listener = listen(); sendBroadCast(); System.in.read(); List<Device> devicesAndClose = listener.getDevicesAndClose(); for (Device device : devicesAndClose) { System.out.println("device:" + device.toString()); } } private static Listener listen () throws Exception { System.out.println("开始监听" ); CountDownLatch countDownLatch = new CountDownLatch(1 ); Listener listener = new Listener(LISTEN_PORT, countDownLatch); listener.start(); countDownLatch.await(); return listener; } private static class Device { private String sn; private int port; private String ip; public Device (String sn, int port, String ip) { this .sn = sn; this .port = port; this .ip = ip; } public int getPort () { return port; } public void setPort (int port) { this .port = port; } public String getIp () { return ip; } public void setIp (String ip) { this .ip = ip; } public String getSn () { return sn; } public void setSn (String sn) { this .sn = sn; } @Override public String toString () { return "Device{" + "sn='" + sn + '\'' + ", port=" + port + ", ip='" + ip + '\'' + '}' ; } } private static class Listener extends Thread { private final int listenPort; private final CountDownLatch countDownLatch; private final List<Device> devices = new ArrayList<>(); private boolean done = false ; private DatagramSocket ds = null ; public Listener (int listenPort, CountDownLatch countDownLatch) { this .listenPort = listenPort; this .countDownLatch = countDownLatch; } @Override public void run () { try { countDownLatch.countDown(); ds = new DatagramSocket(listenPort); while (!done) { final byte [] buf = new byte [512 ]; DatagramPacket receivePack = new DatagramPacket(buf, buf.length); ds.receive(receivePack); String ip = receivePack.getAddress().getHostAddress(); int port = receivePack.getPort(); int dataLen = receivePack.getLength(); String data = new String(receivePack.getData(), 0 , dataLen); System.out.println("UDP Searcher receive from ip:" + ip + "\t port:" + port + "\t data" + data); String sn = MessageCreator.parseSn(data); if (sn != null ) { Device device = new Device(sn, port, ip); devices.add(device); } } } catch (Exception ignored) { } finally { close(); } System.out.println("UDPSearcher listener finished" ); } private void close () { if (ds != null ) { ds.close(); ds = null ; } } List<Device> getDevicesAndClose () { done = true ; close(); return devices; } } public void broadCast () { System.out.println("UDPSearcher sendBroadcast started" ); DatagramSocket ds = new DatagramSocket(); String requestData = MessageCreator.buildWithPort(LISTEN_PORT); byte [] requestDataBytes = requestData.getBytes(); DatagramPacket requestPacket = new DatagramPacket(requestDataBytes, requestDataBytes.length); requestPacket.setAddress(Inet4Address.getByName("255,255,255,2555" )); requestPacket.setPort(20000 ); ds.send(); ds.close(); System.out.println("UpdSearcher sendBroadcast finish" ); } }