文章目录
-
- Java网络编程入门
-
- [1. 初始网络编程](#1. 初始网络编程)
-
- [1.1 什么是网络编程?](#1.1 什么是网络编程?)
- [1.2 网络编程能做什么?](#1.2 网络编程能做什么?)
- [2. 网络编程三要素](#2. 网络编程三要素)
- [3. IP地址](#3. IP地址)
-
- [3.1 什么是IP?](#3.1 什么是IP?)
- [3.2 IPv4的小细节](#3.2 IPv4的小细节)
- [3.3 InetAddress类的使用](#3.3 InetAddress类的使用)
- [4. 端口号](#4. 端口号)
-
- [4.1 什么是端口?](#4.1 什么是端口?)
- [4.2 端口范围](#4.2 端口范围)
- [4.3 常用端口](#4.3 常用端口)
- [5. 协议](#5. 协议)
-
- [5.1 TCP vs UDP](#5.1 TCP vs UDP)
- [5.2 三次握手(TCP建立连接)](#5.2 三次握手(TCP建立连接))
- [5.3 四次挥手(TCP断开连接)](#5.3 四次挥手(TCP断开连接))
- [6. UDP协议](#6. UDP协议)
-
- [6.1 UDP发送数据](#6.1 UDP发送数据)
- [6.2 UDP接收数据](#6.2 UDP接收数据)
- [6.3 UDP单播、组播、广播](#6.3 UDP单播、组播、广播)
- [7. TCP协议](#7. TCP协议)
-
- [7.1 TCP发送数据](#7.1 TCP发送数据)
- [7.2 TCP接收数据](#7.2 TCP接收数据)
- [7.3 中文乱码问题](#7.3 中文乱码问题)
- [8. 网络编程架构:C/S 和 B/S](#8. 网络编程架构:C/S 和 B/S)
-
- [8.1 C/S架构(Client-Server,客户端/服务器)](#8.1 C/S架构(Client-Server,客户端/服务器))
- [8.2 B/S架构(Browser-Server,浏览器/服务器)](#8.2 B/S架构(Browser-Server,浏览器/服务器))
- [8.3 C/S vs B/S 对比](#8.3 C/S vs B/S 对比)
- [9. 常见异常及原因](#9. 常见异常及原因)
- [10. 易错点总结](#10. 易错点总结)
- [11. 总结](#11. 总结)
Java网络编程入门
1. 初始网络编程
1.1 什么是网络编程?
网络编程就是让不同电脑上的程序能够互相通信。
- 单机程序:自己跟自己玩
- 网络程序:可以跟别人玩
1.2 网络编程能做什么?
| 应用 | 例子 |
|---|---|
| 即时通讯 | 微信、QQ |
| 文件传输 | 百度网盘、FTP |
| 远程控制 | 向日葵、TeamViewer |
| Web服务 | 浏览器访问网站 |
2. 网络编程三要素
| 要素 | 作用 | 类比 |
|---|---|---|
| IP地址 | 找到哪台电脑 | 小区地址 |
| 端口号 | 找到电脑上哪个程序 | 门牌号 |
| 协议 | 数据怎么传 | 快递规则 |
3. IP地址
3.1 什么是IP?
IP地址是网络中每台电脑的唯一标识。
IPv4:
- 32位,4个字节
- 格式:
192.168.1.1 - 最大数量:约42亿个(实际不够用)
解决:利用局域网IP解决IP不够的问题
IPv6:
- 128位,16个字节
- 格式:
2001:0db8:85a3:0000:0000:8a2e:0370:7334 - 数量:多到地球上每粒沙子都能分配一个
3.2 IPv4的小细节
特殊IP:
| IP地址 | 含义 |
|---|---|
127.0.0.1 |
本机地址(localhost) |
0.0.0.0 |
所有网卡地址 |
255.255.255.255 |
广播地址 |
私有IP(内网使用,不能上网):
10.0.0.0 ~ 10.255.255.255172.16.0.0 ~ 172.31.255.255192.168.0.0 ~ 192.168.255.255
3.3 InetAddress类的使用
java
public static void main(String[] args) throws UnknownHostException {
static InetAddress getByName(String host) // 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName() // 获取此IP地址的主机名
String getHostAddress() // 返回文本显示中的IP地址字符串
//1. 获取InetAddress的对象
//IP的对象 一台电脑的对象
InetAddress address = InetAddress.getByName("DESKTOP-503JSAM");
System.out.println(address);
String name = address.getHostName();
System.out.println(name); // DESKTOP-503JSAM
String ip = address.getHostAddress();
System.out.println(ip); // 192.168.1.100
}
4. 端口号
4.1 什么是端口?
电脑上同时运行很多程序,数据到了之后该给谁?
端口号 就是程序在网络中的门牌号。
一个端口对应一个应用
4.2 端口范围
- 0 ~ 65535(共65536个)
- 0 ~ 1023:系统保留端口
- 1024 ~ 49151:注册端口
- 49152 ~ 65535:动态/私有端口
4.3 常用端口
| 端口 | 协议 | 用途 |
|---|---|---|
| 80 | HTTP | 网页访问 |
| 443 | HTTPS | 安全网页 |
| 21 | FTP | 文件传输 |
| 22 | SSH | 安全远程登录 |
| 3306 | MySQL | 数据库 |
5. 协议
5.1 TCP vs UDP
| 维度 | TCP | UDP |
|---|---|---|
| 连接 | 需要建立连接 | 不需要 |
| 可靠性 | 可靠,不丢数据 | 不可靠,可能丢 |
| 顺序 | 按顺序到达 | 可能乱序 |
| 速度 | 慢 | 快 |
| 应用 | 文件下载、网页 | 视频通话、直播 |
比喻:
- TCP = 打电话(先接通,再说话)
- UDP = 写信(扔邮筒里,不管收不收得到)
5.2 三次握手(TCP建立连接)
客户端 服务器
| |
|------- SYN ---------->| (1) 客户端:我要连接
| |
|<----- SYN+ACK --------| (2) 服务器:好的,你连吧
| |
|------- ACK ---------->| (3) 客户端:收到,开始传数据
| |
5.3 四次挥手(TCP断开连接)
客户端 服务器
| |
|------- FIN ---------->| (1) 客户端:我发完了
| |
|<------ ACK -----------| (2) 服务器:知道了
| |
|<------ FIN -----------| (3) 服务器:我也发完了
| |
|------- ACK ---------->| (4) 客户端:好的,再见
| |
6. UDP协议
6.1 UDP发送数据
java
//发送数据
//1.创建DatagramSocket对象(快递公司)
//细节:
//绑定端口,以后我们就是通过这个端口往外发送
//空参:所有可用的端口中随机一个进行使用
//有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
//2.打包数据
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();
6.2 UDP接收数据
java
//1.创建DatagramSocket对象(快递公司)
//细节:
//在接收的时候,一定要绑定端口
//而且绑定的端口一定要跟发送的端口保持一致
DatagramSocket ds = new DatagramSocket(10086);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
InetAddress address = dp.getAddress();
int port = dp.getPort();
System.out.println("接收到数据" + new String(data, 0, len));
System.out.println("该数据是从" + address + "这台电脑中的" + port + "这个端口发出的");
//4.释放资源
ds.close();
6.3 UDP单播、组播、广播
| 类型 | 说明 | 目标 |
|---|---|---|
| 单播 | 一对一 | 特定一个IP |
| 组播 | 一对多(加入组) | 组播地址(224.0.0.0 ~ 239.255.255.255) |
| 广播 | 一对所有 | 255.255.255.255 |
java
// 广播示例:发送到广播地址
DatagramPacket packet = new DatagramPacket(data, data.length,
InetAddress.getByName("255.255.255.255"), 8888);
组播:
java
public class SendMessageDemo {
public static void main(String[] args) throws IOException {
/*
组播发送端代码
*/
//创建MulticastSocket对象
MulticastSocket ms = new MulticastSocket();
// 创建DatagramPacket对象
String s = "你好,你好!";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("224.0.0.1");
int port = 10000;
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, address, port);
// 调用MulticastSocket发送数据方法发送数据
ms.send(datagramPacket);
// 释放资源
ms.close();
}
}
java
public class ReceiveMessageDemo1 {
public static void main(String[] args) throws IOException {
/*
* 组播接收端代码
*/
//1. 创建MulticastSocket对象
MulticastSocket ms = new MulticastSocket(10000);
//2. 将当前本机,添加到224.0.0.1的这一组当中
InetAddress address = InetAddress.getByName("224.0.0.1");
ms.joinGroup(address);
//3. 创建DatagramPacket数据包对象
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//4. 接收数据
ms.receive(dp);
//5. 解析数据
byte[] data = dp.getData();
int len = dp.getLength();
String ip = dp.getAddress().getHostAddress();
String name = dp.getAddress().getHostName();
System.out.println("ip为: " + ip + ",主机名为: " + name + "的人。发送了数据: " + new String(data, 0, len));
//6. 释放资源
ms.close();
}
}
7. TCP协议
7.1 TCP发送数据
java
public class Client {
static void main() throws IOException {
//创建Socket对象
Socket socket = new Socket("192.168.1.79", 10086);
//获取输入流
OutputStream os = socket.getOutputStream();
os.write("hi".getBytes());
//关闭
os.close();
socket.close();
}
}
7.2 TCP接收数据
java
public class Server {
static void main() throws IOException {
//创建ServerSocket对象
ServerSocket ss = new ServerSocket(10086);
//监听客户端连接
Socket socket = ss.accept();
//获取输出流
InputStream is = socket.getInputStream();
int b;
while((b = is.read()) != -1){
System.out.println((char) b);
}
//关闭
socket.close();
ss.close();
}
}
7.3 中文乱码问题
字节流直接处理中文可能乱码,用转换流解决:
java
//获取输出流
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int b;
while((b = isr.read()) != -1){
System.out.println((char) b);
}
8. 网络编程架构:C/S 和 B/S
8.1 C/S架构(Client-Server,客户端/服务器)
特点:
- 需要安装专门的客户端软件
- 客户端和服务器都需要开发
- 客户端可以分担计算压力
例子:微信、QQ、游戏、网络编程的Socket例子
┌────────┐ ┌────────┐
│ 客户端1 │◄────网络──────────►│ │
└────────┘ │ 服务器 │
┌────────┐ │ │
│ 客户端2 │◄──────────────────►│ │
└────────┘ └────────┘
8.2 B/S架构(Browser-Server,浏览器/服务器)
特点:
- 客户端就是浏览器,无需安装
- 只需要开发服务器
- 更新方便(改服务器即可)
例子:淘宝、百度、B站
┌────────┐ ┌────────┐
│ 浏览器1 │◄────HTTP──────────►│ │
└────────┘ │ Web │
┌────────┐ │ 服务器 │
│ 浏览器2 │◄──────────────────►│ │
└────────┘ └────────┘
8.3 C/S vs B/S 对比
| 维度 | C/S | B/S |
|---|---|---|
| 客户端 | 需要安装 | 只需要浏览器 |
| 更新 | 每个客户端都要更新 | 服务器更新即可 |
| 性能 | 客户端可分担 | 主要靠服务器 |
| 跨平台 | 需要不同版本 | 浏览器都支持 |
| 开发成本 | 高(两端都要写) | 低(只写服务器) |
| 用户体验 | 更好 | 依赖网络 |
| 学习内容 | Socket编程 | HTTP + Web框架 |
9. 常见异常及原因
| 异常 | 原因 |
|---|---|
ConnectException |
服务器没启动或端口不对 |
BindException |
端口被占用 |
SocketTimeoutException |
连接或读取超时 |
UnknownHostException |
域名解析失败 |
10. 易错点总结
-
先启动服务端,再启动客户端
-
端口不要用1024以下(系统保留)
-
UDP接收时,端口要和服务端绑定的端口一致
-
TCP用字符流处理中文要加flush,否则数据不发送
-
readLine需要换行符 ,发送端要加
writer.newLine() -
关闭资源要按顺序
11. 总结
| 知识点 | 核心内容 |
|---|---|
| IP地址 | 找到电脑(InetAddress) |
| 端口号 | 找到程序(0~65535) |
| UDP | 无连接、不可靠、快(DatagramSocket) |
| TCP | 有连接、可靠、慢(Socket/ServerSocket) |
| C/S | 客户端+服务器,需安装 |
| B/S | 浏览器+服务器,无需安装 |