在网络上传输数据,或者说是在两台计算机之间通讯。把信息“String = "hello"”发送出去,还被另外一台电脑接收并打印出来,需要完成如下的工作:
开始描述过程之前,先明确一些概念,就是数据在穿越 tcp/ip 协议栈时不同阶段的名称:应用层 叫做 消息(message);传输层 叫做 段(segment);网络层 叫做 数据报(datagram)、数据包(packet);数据链路层 叫做 帧(frame)。那么传输的发送过程简单表达就是:{ 消息 -> 段 -> 数据报/数据包 -> 帧 } 。接收过程刚好相反。
- 把 应用层 的信息(字符串等)封装成数据包(数据包是传输层对于信息传递的叫法),进入到 传输层。封装程序包时一项重要工作就是为数据包添加 port 号。
- 传输层的数据,继续封装进入下一层 网络层 ,这时封装有个关键信息,就是添加 ip地址。
- 数据链路层 接收到的信息,继续封装,添加的信息是 MAC 地址。在数据链路层封装后还会交给更底层的协议处理。
上面过程,描述的就是信息发送的四个状态,三个过程。反映到程序中就是 数据打包、信息发送。数据打包通过类 DatagramPacket 完成,信息发送 通过类 DatagramSocket 完成。
1.数据报套接字 类
DatagramSocket 类,用来发送和接收数据报的套接字。
构造方法格式 | 说明 |
public DatagramSocket() | 构造数据报套接字,绑定到本地任何确定的可用端口 |
public DatagramSocket(int port) | 绑定到指定端口的套接字 |
public DatagramSocket(int port, InetAddress laddr) | 绑定到指定的端口、指定的地址 |
1.1.发送数据
使用 DatagramSocket 类的 发送方法 发送数据报数据。
1.1.创建发送Socket对象
直接使用构造函数生成就可以了。
1.2.创建数据并打包
Java 提供了一个类,叫“数据报”类,使用该类提供的方法,生产我们要发送的数据报。
1.3.发送数据
1.4.释放资源
发送代码:
1 public class SendUdpDemo { 2 public static Scanner sc = new Scanner(System.in); 3 4 public static void main(String[] args) throws IOException { 5 InetAddress address = InetAddress.getLocalHost(); 6 int port = 5251; 7 8 // 创建发送对象 9 DatagramSocket dsSendMessage = new DatagramSocket(); 10 11 // 打包数据 12 byte[] buf = getBuf(); 13 DatagramPacket message = packingData(buf, address, port); 14 // 发送数据 15 dsSendMessage.send(message); 16 17 // 释放资源 18 dsSendMessage.close(); 19 } 20 21 // 打包数据 22 public static DatagramPacket packingData(byte[] buf, InetAddress address, int port) { 23 int length = buf.length; 24 DatagramPacket dp = new DatagramPacket(buf, length, address, port); 25 26 return dp; 27 } 28 29 // 收集数据 30 public static byte[] getBuf() { 31 System.out.print("输入要发送信息:"); 32 String inputString = sc.nextLine(); 33 byte[] buf = inputString.getBytes(); 34 35 return buf; 36 } 37 }
1.2.接收数据
使用 DatagramSocket 类的 接收方法 接收数据报数据。
1.2.1.创建接收Socket对象
1.2.2.接收数据
1.2.3.解析数据
1.2.4.输出数据
1.2.5.释放资源
接收数据代码:
1 public class ReceiveUdpDemo { 2 3 public static void main(String[] args) throws IOException { 4 // 创建接收对象 5 int listenPort = 5251; 6 // DatagramSocket dsReceiveMessage = new DatagramSocket(listenPort); 7 DatagramSocket dsReceiveMessage = new DatagramSocket(listenPort, InetAddress.getLocalHost()); 8 9 // 接收数据 10 byte[] buf = new byte[1024 * 8]; 11 int length = buf.length; 12 DatagramPacket p = new DatagramPacket(buf, length); 13 dsReceiveMessage.receive(p); 14 15 // 解析数据 16 byte[] data = p.getData(); 17 int len = data.length; 18 19 // 输出数据 20 System.out.println(new String(data, 0, len)); 21 22 // 释放资源 23 dsReceiveMessage.close(); 24 25 } 26 }
2.数据报 类
此类,表示“数据报”,用来实现无连接包投递服务。
收发 | 构造方法格式 | 参数 | 说明 |
发送 | public DatagramPacket(byte[] buf, int len, InetAddress add, int port) | buf,发送出去的数据 | 构造对象,用来把数据包发送到指定地址、端口 |
接收 | public DatagramPacket(byte[] buf, int len) | buf,保存接收到的内容 | 构造对象,接收长度为len的数据 |
- 构造发送对象,参数 len 控制包的大小,add 是目标地址, port 是目标端口。把 buf 数组的内容发送出去。
- 构造接收对象,参数 len 是说接收发过来的单个数据包的大小。接收到到的内容保存到 buf 数组。