Java基础学习(十七)
Java基础学习(十七):网络编程
本文为个人学习记录,内容学习自 黑马程序员
概念
- 定义:在网络通信协议下,不同计算机上运行的程序进行的数据传输
- 常见的软件架构:C/S 和 B/S
- C/S:Client/Server,在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序
- B/S:Browser/Server,用户通过浏览器的不同网址即可访问不同的服务器
- C/S 和 B/S 的比较:
- C/S 需要开发客户端,适合定制专业化的办公类软件,例如 IDEA、网游
- B/S 不需要开发客户端,适合移动互联网应用,例如新闻网页
- 网络编程三要素:IP、端口号、协议
- IP:设备在网络中的地址,是唯一的标识
- 端口号:应用程序在设备中唯一的标识
- 协议:数据在网络中传输的规则,常见的协议有 UDP、TCP、http、https、ftp
IP
-
定义:全称 Internet Protocol,互联网协议地址,也称 IP 地址,是分配给上网设备的数字标签
-
常见分类:IPv4、IPv6
-
IPv4:Internet Protocol version 4,互联网通信协议第四版
- 采用 32 位地址长度,分成 4 组
- 通常采用点分十进制表示,例如 11000000 10101000 00000001 01000010 表示为 192.168.1.66(没有负数)
-
IPv6:Internet Protocol version 6,互联网通信协议第六版
- 采用 128 位地址长度,分成 8 组
- 通常采用冒分十六进制表示
-
现状:IPv4 不够用,但 IPv6 还未普及,IPv4 仍是使用的主流,为了节省 IP 地址,又将 IPv4 的地址分成了公网地址(万维网使用)和私有地址(局域网使用),192.168. 开头的就是私有地址,专门为组织机构内部使用,例如网吧中的电脑共享一个对外的公网 IP,再由路由器给其中的每一台电脑分配局域网 IP
-
特殊 IP 地址:127.0.0.1,也称为 localhost,是本地回环地址,也即本机 IP
-
举例:假如本机 IP 的局域网地址为 192.168.1.100,那么通过 192.168.1.100 和 127.0.0.1 都可以访问到本机,但前者需要经由路由器才能将信息发送到本机,而后者可以直接发送到本机,并且前者在不同路由器下分配的地址可能不同,而后者固定不变
-
常见 CMD 命令:
- ipconfig:查看本机 IP 地址
- ping:检查网络是否连通
-
InetAddress
常用方法 说明 static InetAddress getByName(String host) 确定主机名称的 IP 地址,主机名称可以是机器名称,也可以是 IP 地址 String getHostName() 获取此 IP 地址的主机名 String getHostAddress() 返回文本显示中的 IP 地址字符串 public class Test { public static void main(String[] args) throws UnknownHostException { InetAddress address = InetAddress.getByName("10.250.206.75"); String name = address.getHostName(); String ip = address.getHostAddress(); } }
端口号
- 端口号是应用程序在设备中的唯一标识
- 端口号由两个字节表示,取值范围:0 ~ 65535,其中 0 ~ 1023 端口号用于一些知名的网络服务或者应用
协议
计算机网络中,连接和通信的规则被称为网络通信协议
- OSI 参考模型:世界互联协议标准,全球通信规范,由于过于理想化而未能推广
- TCP/IP 参考模型(TCP/IP协议):事实上的国际标准
UDP 通信
-
User Datagram Protocol,用户数据报协议
-
面向无连接的通信协议,速度快,有大小限制一次最多发送 64K,数据不安全,易丢失数据
-
UDP 通信程序(发送数据)
-
步骤:① 创建发送端的 DatagramSocket 对象 ② 数据打包(DatagramPacket) ③ 发送数据 ④ 释放资源
-
代码实现:
public class Test { public static void main(String[] args) throws IOException { // 1.创建DatagramSocket对象 // 需要绑定端口,之后就从这个端口向外发送 // 采用空参构造时,从所有可用端口中随机选择绑定 // 采用有参构造时,指定端口号进行绑定 DatagramSocket ds = new DatagramSocket(); // 2.打包数据 // 创建DatagramPacket对象进行数据打包,DatagramPacket有多种构造方法,下面列举其中一种 // 第一个参数为要发送的字节数组 // 第二个参数为要发送数据的长度 // 第三个参数为目标IP地址,为InetAddress对象 // 第四个参数为目标端口 String str = "你好"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName("127.0.0.1"); int port = 10086; DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); // 3.发送数据 ds.send(dp); // 4.释放资源 ds.close(); } }
-
-
UDP 通信程序(接收数据)
-
步骤:① 创建接收端的 DatagramSocket 对象 ② 接收打包好的数据 ③ 解析数据包 ④ 释放资源
-
代码实现:
public class Receive { public static void main(String[] args) throws IOException { // 1.创建DatagramSocket对象 // 接收时必须绑定端口,并且端口号必须和发送端的目标端口一致 DatagramSocket ds = new DatagramSocket(10086); // 2.接收数据包 // 创建DatagramPacket对象进行数据打包,DatagramPacket有多种构造方法,在接收数据时只需要指定接收数组和长度 // receive()方法是阻塞的 byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); ds.receive(dp); // 3.解析数据包 // 可以获取数据包中的数据值、数据长度、发送端IP地址对象、发送端端口号 byte[] data = dp.getData(); int len = dp.getLength(); InetAddress address = dp.getAddress(); int port = dp.getPort(); System.out.println(new String(data, 0, len)); // 4.释放资源 ds.close(); } }
-
-
UDP 的三种通信方式:单播、组播、广播
-
单播:一个发送端,一台电脑作为接收端
- 上面的代码即是单播的实现
-
组播:一个发送端,一组电脑作为接收端
-
组播地址:224.0.0.0 ~ 239.255.255.255,其中 224.0.0.0 ~ 224.0.0.255 为预留给个人的组播地址
-
代码实现(发送端)
public class Send { public static void main(String[] args) throws IOException { // 1.创建MulticastSocket对象 MulticastSocket ms = new MulticastSocket(); // 2.打包数据 // 目标IP地址为组播地址中 String str = "你好"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName("224.0.0.1"); int port = 10000; DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); // 3.发送数据 ms.send(dp); // 4.释放资源 ms.close(); } }
-
代码实现(接收端)
public class Receive { public static void main(String[] args) throws IOException { // 1.创建MulticastSocket对象 MulticastSocket ms = new MulticastSocket(10000); // 2.将本机添加到要使用的组播地址中 InetAddress address = InetAddress.getByName("224.0.0.1"); ms.joinGroup(address); // 3.接收数据包 byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); ms.receive(dp); // 4.解析数据包 byte[] data = dp.getData(); int len = dp.getLength(); InetAddress ip = dp.getAddress(); int port = dp.getPort(); // 5.释放资源 ms.close(); } }
-
-
广播:一个发送端,局域网中所有电脑都是接收端
-
广播地址:255.255.255.255
-
代码实现(发送端)
public class Send { public static void main(String[] args) throws IOException { // 1.创建DatagramSocket对象 DatagramSocket ds = new DatagramSocket(); // 2.打包数据 // 目标IP地址为广播地址 String str = "你好"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName("255.255.255.255"); int port = 10000; DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); // 3.发送数据 ds.send(dp); // 4.释放资源 ds.close(); } }
-
-
TCP 通信
-
Transmission Control Protocol,传输控制协议
-
面向连接的通信协议,速度慢,没有大小限制,数据安全
-
TCP 通信协议是一种可靠的网络协议,它在通信的两端各建立一个 Socket 对象,通信之前要保证连接已经建立,通过 Socket 产生 IO 流来进行网络通信
-
TCP 通信程序(客户端)
-
步骤:① 创建客户端的 Socket 对象(Socket)与指定服务端连接 ② 获取输出流 ③ 写数据 ④ 释放资源
-
代码实现:
public class Client { public static void main(String[] args) throws IOException { // 1.创建Socket对象 // 参数一:要连接的IP地址 // 参数二:要连接的端口号 // 注意:如果连接不上,代码会报错(必须先启动服务器端,再启动客户端) Socket socket = new Socket("127.0.0.1", 10000); // 2.从连接通道中获取输出流 // 需要注意:客户端也能使用socket.getInputStream()获取输入流,从服务端接收数据 OutputStream os = socket.getOutputStream(); // 3.向输出流中写入数据 os.write("你好".getBytes()); // 4.释放资源 // 释放socket时也会释放内部的输出流 socket.close(); } }
-
-
TCP 通信程序(服务器端)
-
步骤:① 创建服务器端的 Socket 对象(ServerSocket) ② 监听客户端连接,返回一个 Socket 对象 ③ 获取输入流,读数据 ④释放资源
-
代码实现:
public class Server { public static void main(String[] args) throws IOException { // 1.创建ServerSocket对象 // 参数为绑定的端口号,需要和客户端要连接的端口号一致 ServerSocket ss = new ServerSocket(10000); // 2.监听客户端的连接 // 这一步会阻塞程序 Socket socket = ss.accept(); // 3.从连接通道中获取输入流,读取数据 // 需要注意:服务端也能使用socket.getOutputStream()获取输出流,向客户端写入数据 InputStream is = socket.getInputStream(); // (可选)为了正确读取中文,需要使用转换流 InputStreamReader isr = new InputStreamReader(is, "UTF-8"); int b; // read()方法会从连接通道中读取数据,只有读取到结束标记时返回值才为-1 // 结束标记一般有两种写法: // 1.在客户端使用socket.shutdownOutput()关闭输出流 // 2.在客户端使用socket.close()关闭socket while ((b = isr.read()) != -1) { System.out.print((char) b); } // 4.释放资源 // 释放socket时也会释放内部的输入流 socket.close(); ss.close(); } }
-
-
TCP 通信中的“三次握手”和“四次挥手”:
-
三次握手
-
四次挥手
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix