## IP地址
在IPv4中,一共有五类IP地址
* A类地址:网络号占1个字节。网络号的第一位固定为0。
* B类地址:网络号占2个字节。网络号的前两位固定为10。
* C类地址:网络号占3个字节。网络号的前三位固定位110。
* D类地址:前四位是1110,用于多播(multicast),即一对多通信。
* E类地址:前四位是1111,保留为以后使用。
其中,D类地址是从224.0.0.0到239.255.255.255这个范围的。这类地址的主要做用就是用作组播(又叫做多播)。
而ABC类地址是单播地址。
广播地址:主机位全部是1的地址都是广播地址,即``。网络位和主机位全都是1的是本地广播地址,即``,IPV4:255.255.255.255。
## 单播
单播就是一对一通信,我们常用的就是TCP协议,在Java中的体现就是Socket和ServerSocket。有人可能会问,那UDP协议呢?其实UDP协议即可以用来做单播又可以用来做多播和广播。Java中,处理UDP对应的是DatagramSocket。
下面我们分别使用TCP和UDP实现一个服务端客户端。
### 基于TCP的实现
TCP服务端:
服务端监听本地端口9999,然后等待客户端输入,将客户端的输入原样输出给客户端。
``` java
/**
* Date: 2016年1月6日 下午1:16:57
* TCP服务端,监听端口,等待连接,然后将客户端的输入的内容原样返回给客户端
*/
public class TCPUnicastServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = null;
try {
// 服务端,绑定到端口9999
serverSocket = new ServerSocket(9999);
while (true) {
final Socket clientSocket = serverSocket.accept();
// 启动一个线程,处理客户端连接
new Thread() {
@Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
// 监听客户端的输入
while (true) {
String requestData = reader.readLine();
if (requestData == null) {
break;
}
System.out.println("server received:" + requestData);
// 将客户端的输入原样返回给客户端
writer.println(requestData);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
}
}
}
}
}
```
TCP客户端:
客户端负责与客户端建立连接,并向服务端发送数据,同时接受服务端返回的结果。
``` java
public static void main(String[] args) throws Exception {
// 向服务端创建连接
Socket socket = new Socket("127.0.0.1", 9999);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
// 发送数据
writer.println("Hello,i am client");
writer.flush();
// 等待服务端响应
while (true) {
String serverData = reader.readLine();
if (serverData == null) {
break;
}
System.out.println("client received:" + serverData);
}
socket.close();
}
```
TCP的实现比较特殊,Socket分为服务端Socket(ServerSocket)和客户端Socket(Socket)。
### 基于UDP的实现
Java中UDP对应的Socket只有一个DatagramSocket,不区分客户端与服务端(想想也是)。
发送数据的一端:
``` java
public static void main(String[] args) throws Exception {
DatagramSocket serverSocket = new DatagramSocket();
// 发送的目的地址和端口
InetAddress destination = InetAddress.getByName("127.0.0.1");
for (int i = 0; i < 10; i++) {
byte[] buf = "Hello client".getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, destination, 9999);
serverSocket.send(packet);
TimeUnit.SECONDS.sleep(5);
}
serverSocket.close();
}
```
接收数据的一端:
``` java
public static void main(String[] args) throws Exception {
DatagramSocket clientSocket = new DatagramSocket(9999);
while (true) {
DatagramPacket packet = new DatagramPacket(new byte[256], 256);
clientSocket.receive(packet);
System.out.println(new String(packet.getData()).trim());
}
}
```
说明:
1. 发送端和接收端都使用DatagramSocket
2. 发送端发送的时候指定的地址是一个单播地址
3. 发送和接收数据使用的是DatagramPacket
## 多播
多播就是一对多通信,即从一台机器发送数据到多台机器。在Java里的体现就是MulticastSocket,MulticastSocket是DatagramSocket的子类。
很多人喜欢将多播称作组播,是因为多播不同于广播,广播是向所有机器发送数据,而多播是针对某一组机器发送数据。下面我们来看一下多播的实现。
发送数据的一端:
``` java
public static void main(String[] args) throws Exception {
// 指定组播要发送的组
InetAddress group = InetAddress.getByName("224.0.0.3");
// 创建MulticastSocket,它是DatagramSocket的子类
MulticastSocket socket = new MulticastSocket();
for (int i = 0; i < 10; i++) {
String data = "hello client";
byte[] bytes = data.getBytes();
// 将数据发送到对应组的对应端口
socket.send(new DatagramPacket(bytes, bytes.length, group, 9999));
TimeUnit.SECONDS.sleep(5);
}
socket.close();
}
```
接收数据的一端:
``` java
public static void main(String[] args) throws IOException {
// 多播客户端监听相应的端口
MulticastSocket clientSocket = new MulticastSocket(9999);
// 客户端将自己加入到指定的多播组中,这样就能收到来自这个组的消息
InetAddress group = InetAddress.getByName("224.0.0.3");
clientSocket.joinGroup(group);
byte[] buf = new byte[256];
while (true) {
// 读取数据
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(msgPacket.getData());
System.out.println("Socket 1 received msg: " + msg.trim());
}
//离开组
//clientSocket.leaveGroup(group);
}
```
说明:
1. 多播发送端和接收端使用的都是MulticastSocket,它是DatagramSocket的一个子类,其实在底层,多播也是基于UDP的。
2. 客户端需要加入到对应的group中,才可以接收到服务端的消息:`clientSocket.joinGroup(group);`
## 广播
广播分组的目标IP地址的主机部分全为1,这意味着本地网络(广播域)中的所有主机都将接收并查看该分组。诸如ARP和DHCP等很多网络协议都使用广播。
例如:
1. C类网络192.168.1.0的默认子网掩码为255.255.255.0,其广播地址为192.168.1.255,其主机部分为十进制数255或二进制数11111111(全为1)。
2. B类网络172.16.0.0的默认子网掩码为255.255.0.0,其广播地址为172.16.255.255。
3. A类网络10.0.0.0的默认子网掩码为255.0.0.0,其广播地址为10.255.255.255。
在java中,广播也是借助DatagramSocket实现的。
消息发送方
``` java
public static void main(String[] args) throws Exception {
DatagramSocket serverSocket = new DatagramSocket();
// 发送的目的地址和端口
InetAddress destination = InetAddress.getByName("255.255.255.255");
for (int i = 0; i < 10; i++) {
byte[] buf = "Hello client".getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, destination, 9999);
serverSocket.send(packet);
TimeUnit.SECONDS.sleep(5);
}
serverSocket.close();
}
```
注意:发送的地址必须是广播地址。
消息接收方
``` java
public static void main(String[] args) throws Exception {
DatagramSocket clientSocket = new DatagramSocket(9999);
while (true) {
DatagramPacket packet = new DatagramPacket(new byte[256], 256);
clientSocket.receive(packet);
System.out.println(new String(packet.getData()).trim());
}
}
```
其实仔细观察一下你会发现,在前面的UDP实现单播的时候的代码与广播的代码基本是一样的,区别就在于单播的时候目的端的地址必须是单播地址,而广播的时候,目的端的地址必须是广播地址。
## 单播,组播,广播都有哪些应用场景?
1. 单播:点对点通信,最常用的就是TCP协议。
2. 组播:一对多通信,视频教学:多个学生连接到同一个服务端。
3. 广播:一对多通信,DHCP动态分配IP地址的时候,客户机器就是通过发送一个广播信息,只有DHCP服务器才会对这个广播信息进行响应。
## 总结
1. IPv4地址分为五类,其中ABC三类都是单播地址,D类是多播地址,地址范围为224.0.0.0到239.255.255.255。
2. 广播地址:地址位都为1。网络位和地址位都为1的(255.255.255.255)为本地广播地址。
3. 广播和多播都是通过UDP协议实现的,在Java中广播是借助DatagramSocket实现,多播是MulticastSocket,后者是前者的子类。
## 扩展阅读
1. http://www.nakov.com/inetjava/lectures/part-1-sockets/InetJava-1.5-UDP-and-Multicast-Sockets.html
2. http://book.51cto.com/art/200904/120471.htm
3. http://colobu.com/2014/10/21/udp-and-unicast-multicast-broadcast-anycast/(这篇文章讲解的非常好)