1. 概念
TCP:需要对方确认,建立连接
UDP:发送就可以,不用管对方
1.1 计算机网络
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通通信协议的管理和协助下,实现资源共享和信息传递的计算机系统。
1.2 网络编程的目的
例如:无线电台(传播信息)数据交换
1.3 想要达到这个效果需要什么
如果定位网络上的一个主机?
-
主机的ip地址,端口号(定位该主机上的某个资源)
找到了这个主机该怎么传输据?
-
JavaWeb:网页编程(B/S)
-
网络编程:TCP/IP(C/S)
2. 网络通信要素
如何实现网络通信?
- 通信双方的地址:ip地址和端口号
- 规则:网络通信的协议(TCP/IP参考模型)
OSI 七层网络模型
TCP/IP 四层概念模型
小结:
1、网络编程中有两个主要问题
- 如何准确的定位到网络上的一台或者多台主机
- 找到主机之后如何进行通信
2、网络编程中的要素
- IP和端口号
- 网络通信协议
3、万物皆对象(IP类、TCP类)
3. IP
ip地址对应的API:InetAddress
- 唯一定位一台网络计算机
- 127.0.0.1:本机localhost
ip地址的分类:
- 根据ip地址进行分类
- ipv4:例如 127.0.0.1,由四个字节组成,每个字节的长度为0-255(42亿,2011年就用尽了)
- ipv6: 例如 240e:33d:2f9a:6600:948c:bd86:7d89:e527,有八个无符号整数来表示 128位
- 根据公网-私网分类(校园网属于私网)
- ABCD类地址
- 192.168.xx.xx专门给组织内部使用(局域网)
- 私网也叫局域网
域名诞生原因:
- 解决记忆ip地址问题
//测试IP
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
InetAddress inetAddress3 = InetAddress.getByName("localhost");
InetAddress inetAddress4 = InetAddress.getLocalHost();
//查询网站ip地址
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
//常用方法
System.out.println(inetAddress2.getAddress());
System.out.println(inetAddress2.getCanonicalHostName());//规范的名字
System.out.println(inetAddress2.getHostAddress());//ip
System.out.println(inetAddress2.getHostName());//域名:或者自己电脑的名字
System.out.println(inetAddress1);
System.out.println(inetAddress2);
System.out.println(inetAddress3);
System.out.println(inetAddress4);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}
4. 端口
端口表示计算机上的一个程序的进程
- 不同的进程有不同的端口号,用来区分软件
- 一个电脑上被规定的可以运行的程序:0-65535
- 每种协议都可以运行该数量(TCP,UDP:65535*2)
- 不能的协议的程序可以拥有相同端口号,相同的协议不能拥有一样的端口号,会冲突!
端口分类:
- 公有端口 0-1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
程序注册端口 1024-49151(用来分配给用户和程序的)
- Tomcat:8080
- MySQL:3306
- Oracle:1521
动态、私有端口 49152-65535
//查看所有程序进程端口
netstat -ano
//查看某个具体的端口(用来检测哪个端口冲突)
netstat -ano|findstr "3306"
//查看指定端口的进程
tasklist|findstr "8696"
PID和端口号的区别?
- 端口号是系统分配给每个进程的唯一标识符
- pid是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的pid。进程中止后pid被系统回收,可能会被继续分配给新运行的程序;
配置本机的映射地址:(用来干嘛的?)
在网络上访问网站,要首先通过DNS域名服务器把网络域名(类似这样的www.xx.com)解析成IP地址后,我们的计算机才能访问。要是对于每个域名请求我们都要等待域名服务器解析后返回IP信息,这样访问网络的效率就会降低,而Hosts文件就能提高解析效率。根据Windows系统规定,在进行DNS请求以前,Windows系统会先检查自己的Hosts文件中是否有这个地址映射关系,如果有则调用这个IP地址映射,如果没有再向已知的DNS 服务器提出域名解析。也就是说Hosts的请求级别比DNS高
5. 通信协议
协议:约定,就好比我们工作上说的普通话
网络通信协议:传输速率…
TCP/IP协议簇:是Internet的基础,也是当今最流行的组网形式。TCP/IP是一组协议的代名词,包括许多别的协议,组成了TCP/IP协议簇。其中比较重要的有SLIP协议、PPP协议、IP协议、ICMP协议、ARP协议、TCP协议、UDP协议、FTP协议、DNS协议、SMTP协议等
几个重要的协议:
- TCP:用户传输协议
- UDP:用户数据报协议
出名的协议:
- TCP
- IP:互联网协议
TCP和UDP对比:
TCP:打电话
- 连接、稳定
- 三次握手、四次挥手
三次握手(最少需要三次来保证稳定连接)
A:你瞅啥!
B:瞅你咋地!
A:干一场!
四次挥手
A:我要走了
B:你真的要走了吗
B:你真的真的要走了吗
A:我真的要走了
- 客户端、服务端
- 建立连接,传输完成,释放连接,效率低
UDP:发短信
- 不需要连接,不稳定
- 客户端、服务端(界限不是很明确)
- “导弹”目标明确,不管对方释放准备好
- DDOS洪水攻击(发生垃圾短信阻塞线路)
6. TCP
打电话:建立连接-传输完成-摧毁连接
6.1 TCP协议工作流程
- 客户端
- 连接服务器Socket
- 发送消息
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
//1. 要知道服务器的地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
//2. 端口号
int port = 9999;
//3. 创建一个socket 连接
socket = new Socket(serverIP,port);
//4. 发生消息 IO流
os = socket.getOutputStream();
os.write("你好,世界".getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(os!=null){
try {
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
服务端
- 建立服务器端口ServerSocket
- 等待用户的连接accept()
- 接收用户消息
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1. 我有一个地址
serverSocket = new ServerSocket(9999);
while(true){
//2. 等待客户端连接过来
socket = serverSocket.accept();
//3. 读取客户端的消息
is = socket.getInputStream();
//管道流 字符流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while((len=is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
}
/*
byte[] buffer = new byte[1024];
int len;
while((len=is.read(buffer))!=-1){
String msg = new String(buffer,0,len);
System.out.println(msg);
}
*/
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//关闭资源
if(baos!=null){
try {
baos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
先启动服务端进行监听来接收消息,然后客户端根据对应地址发送消息,服务端一接收连接就会做出响应
6.2 文件上传
服务器端
public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
//1. 创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//2. 监听客户端连接
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接
//3. 获取输入流
InputStream is = socket.getInputStream();
//4. 文件输出
FileOutputStream fos = new FileOutputStream(new File("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/receive.jpg"));
byte[] bytes = new byte[1024];
int len;
while((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
//通知客户端接受完毕
OutputStream os = socket.getOutputStream();
os.write("文件接受完毕,可以断开连接".getBytes());
//5. 关闭资源
os.close();
fos.close();;
is.close();
socket.close();
serverSocket.close();
}
}
客户端
public class TcpClientDemo02 {
public static void main(String[] args) throws IOException {
//1. 创建一个socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2. 创建一个输出流
OutputStream os = socket.getOutputStream();
//3. 读取文件
FileInputStream fis = new FileInputStream(new File("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/baidu1.jpg"));
//4. 写出文件
byte[] bytes = new byte[1024];
int len;
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//通知服务器,我已经结束
socket.shutdownOutput();//我已传输完成
//确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//String byte[];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes2 = new byte[1024];
int len2;
while((len2 = inputStream.read(bytes2))!=-1){
baos.write(bytes2,0,len2);
}
System.out.println(baos.toString());
//5. 关闭
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
7. Tomcat
- 客户端
- 客户端自定义 C
- 浏览器 C
- 服务端
- 服务端自定义 S
- Tomcat S
补充:
- .bat是Windows系统下的执行文件
- .sh是Linux系统下的执行文件
8. UDP
8.1 UDP发送消息
发送短信:不用连接,只需要知道对方的地址!
- 发送端(可以是客户端,也可以是服务端)
//不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception {
//1. 建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2. 建个包
//发生给谁
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
//数据,数据长度起始,结束,要发送给谁
String msg = "你好,服务器!";
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
//3. 发送包
socket.send(packet);
//4. 关闭流
socket.close();
}
}
- 接收端(可以是客户端,也可以是服务端)
//服务器端,开放端口,还是要等待客户端的连接
public class UdpServerDemo01 {
public static void main(String[] args) throws IOException {
//开放端口
DatagramSocket socket = new DatagramSocket(9090);
//接受数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);//接收
socket.receive(packet);//阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关闭连接
socket.close();
}
}
8.2、咨询
发送端
public class UdpSenderDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
//准备数据:控制台读取
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true){
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
socket.send(packet);
if(data.equals("bye")){
break;
}
}
socket.close();
}
}
接收端
public class UdpReceiveDemo02 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while(true){
//准备接受包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet);//阻塞式接收包裹
//断开连接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, packet.getLength());
System.out.println(receiveData);
if(receiveData.equals("bye")){
break;
}
}
socket.close();
}
}
8.3、UDP实现多线程在线咨询
发送端
public class TalkSend implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIp;
private int toPort;
public TalkSend(int fromPort, String toIp, int toPort) {
this.fromPort = fromPort;
this.toIp = toIp;
this.toPort = toPort;
try{
socket = new DatagramSocket(fromPort);
//准备数据:控制台读取
reader = new BufferedReader(new InputStreamReader(System.in));
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String data = null;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIp, this.toPort));
socket.send(packet);
if (data.equals("bye")) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
接收端
public class TalkReceive implements Runnable {
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port, String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
//准备接受包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);//阻塞式接收包裹
//断开连接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, packet.getLength());
System.out.println(msgFrom + ":" + receiveData);
if (receiveData.equals("bye")) {
break;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
socket.close();
}
}
学生
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
老师
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
9. URL
https://www.baidu.com/
URL:统一资源定位符,定位资源的,用来定位互联网上的某个资源
DNS域名解析器:就是把域名(www.baidu.com)解析成ip地址xxx.x.x.x
组成:
协议://IP地址:端口号/项目/资源名
实例:
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=xay&password=123");
System.out.println(url.getProtocol());//协议
System.out.println(url.getHost());//主机ip
System.out.println(url.getPort());//端口号
System.out.println(url.getPath());//文件路径
System.out.println(url.getFile());//文件全路径
System.out.println(url.getQuery());//参数
}
}
通过URL下载资源
public class URLDown {
public static void main(String[] args) throws IOException {
//1. 下载地址
URL url = new URL("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
//2. 连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream is = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/JavaBasics/src/com/net/demo04/test.png");
byte[] bytes = new byte[1024];
int len;
while((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);//写出这个注释
}
fos.close();
is.close();
urlConnection.disconnect();//断开连接
}
}
音乐下载
public class MusicDownload {
public static void main(String[] args) throws IOException {
URL url = new URL("https://m701.music.126.net/20230201161620/fbc4a9b932035588e92df9f6a2f27a3f/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/14096431555/252f/b246/4da5/88c4d262ef5e22cb2a24b7c35922913b.m4a");
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream is = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("/Users/xay/Desktop/编程/JAVA-FullStack/JavaSE/JavaBasics/src/com/net/demo04/abc.m4a");
byte[] bytes = new byte[1024];
int len;
while((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
System.out.println("音乐下载完毕");
fos.close();
is.close();
urlConnection.disconnect();
}
}