一.计算机网络定义
计算机网络是指将地理位置不同具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
二.网络通信协议
- 名义上标准:ISO/OSI参考模型
- 事实上标准:TCP/IP协议栈
我们使用的TCP/IP协议栈前端用到的HTTP多一点,后端的TCP,UDP就都懂得了。
TCP
面向连接的,可靠的,基于字节流的运输层通信协议
特点:
- 面向连接
- 点对点
- 高可靠性:三次握手
- 占用资源高,效率地
说到三次握手,我们就不得不讲讲三次握手和四次挥手的内容了,毕竟这面试被问到也不是一次两次了。
首先我们先简单的了解下报文(豹纹???)
首先看到的是我们每行有4个字节,一行有32位。
第一行的前16是源端口号,后16位是目的端口号
第二行的32位就是序号,第一次随机生成, 就是我们的seq
第三行的32位是确认序号,就是我们ack
然后我们看到第四行的11-16位的6个标志位,他们都只有一位,取值都是0/1,我们这边只了解几个重要的标志位
- ACK:区别于小写的ack,大写ACK是值为0/1的标志位,用来确认是否接收到信息使用
- SYN:在新建立连接时值为1
- FIN:在断开连接时值为1
在简单的了解完报文后,我们说说三次握手和四次挥手的过程
三次握手
- 在客户端在第一次和服务端连接时,我们需要发送一个SYN连接位值为1的标志位,然后发送一个随机生成的seq。
- 然后服务端在接收到来自客户端发来的消息后,服务端会发送确认位ACK值为1的标志位,确认序列ack为客户端发来的seq+1,此时我们的服务端还需要和客户端也建立连接,所以发送的信息还需要带有连接位SYN值为1的标志位和一个随机生成的seq。
- 在客户端接收到服务端传来的报文后,客户端需要发送确认位ACK值为1的标志位,确认序列ack为服务端发来的seq+1和增长后的seq给服务端。
在三次握手后,我们的tcp建立全双工连接。
Q:在两次握手后,不是已经连接上了吗?为什么还要进行第三次握手?
A:在第二次握手完成时,我们的服务端只能确认客户端可以发送消息,客户端可以确认服务端可以收到自己发的消息和自己能收到服务端的传来的消息,但是服务端没办法确认自己发的消息客户端是否收到,所以还需要第三握手来告诉服务端,服务端发的消息客户端可以收到。
四次挥手
- 客户端发送FIN为1的结束标志位,也会带有seq等信息
- 服务端收到后会发送ACK为1的确认标志位,ack信息
- 之后等服务端结束数据传输会再次发送FIN为1的标志位和seq等信息
- 客户端在收到服务端传来的FIN为1的标志位后的信息后关闭连接,并发送ACK确认标志位为1和ack信息
Q:四次挥手的第二步和第三步可以合在一起吗?
A:不能,我们要知道第二步和第三步的意义是什么。第二次挥手是客户端告诉我已经没有数据传了,准备要关闭连接,这个时候服务端可能还在处理这客户端的数据可能还需要回传数据给客户端,这个时候服务端会先发一条ACK给客户端,告诉客户端,我已经收到了你要关闭的信息了,但是你先等等再关,等我消息。然后第三次挥手就是,服务端已经处理好,发送一条FIN为1的报文,告诉客户端我这边处理完毕,可以关闭连接。
UDP
一种无连接传输层协议,提供面向事务的简单不可靠信息传送服务
特点:
- 非面向连接,传输不可靠,可能丢失
- 只管发送,不考虑对方是否接受
- 可广播发送
- 占用资源低,效率高
Q:为什么UDP是不可靠的,我们还要用呢?
A:这里的不可靠不是说UDP靠不住的意思,是UDP不保证消息交付,不保证交付顺序,不跟踪连接状态。这样的好处也和TCP相比也是显而易见,占用资源低,效率高。
TCP和UDP比较
两种连接没有谁好谁差,只是区分场合哪种更适合。
TCP与UDP的适用场景
TCP:
对数据传输的质量有较高要求,但对实时性要求不高。比如HTTP,HTTPS,FTP等传输文件的协议以及POP,SMTP等邮件传输的协议,应选用TCP协议。
UDP:
只对数据传输的实时性要求较高,但不对传输质量有要求。比如视频传输、实时通信等,应选用UDP协议。
三.常用基本概念
1.URL统一资源定位符
- URL:统一资源定位符,由四个部分组成:协议,ip地址或主机域名,端口号,资源文件名
2.常用的概念类
//获取IP等信息
new InetAddress();
//获取ip 端口等信息
new InetSocketAddress();
//获取协议 ip 端口 资源 等信息
new URL();
四.TCP编程
一次双向的TCP编程
package com.wq.socketTCP;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TestSocket {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket向服务端传输数据
Socket socket = new Socket(InetAddress.getLocalHost(),9900);
//2.传输数据到socket
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("name 123@qq.com : pass wangEL");
//3.接收从服务端传来数据
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
String result = dis.readUTF();
System.out.println("从服务端接收到的结果:" + result);
//4.关闭资源
dis.close();
is.close();
dos.close();
os.close();
socket.close();
}
}
package com.wq.socketTCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TestSocketServer {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket接收客户端数据
ServerSocket serverSocket = new ServerSocket(9900);
//2.在指定端口监听
Socket socket = serverSocket.accept();
//3.接收客户端信息并输出
InputStream is = socket.getInputStream();
DataInputStream ds = new DataInputStream(is);
System.out.println("从客户端传来:"ds.readUTF());
//4.回传数据给客户端
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("登陆成功");
//5.关闭资源
dos.close();
os.close();
ds.close();
is.close();
socket.close();
serverSocket.close();
}
}
五.UDP编程
一次双向的UDP编程
package socketUDP;
import java.io.IOException;
import java.net.*;
public class UDPClient {
public static void main(String[] args) throws IOException {
//创建DatagramSocket传输接受对象
DatagramSocket socket = new DatagramSocket(9999);
//接收从客户端传来的数据并输出
String str = "这是一个UDP编程";
DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length,
InetAddress.getLocalHost(), 9980);
socket.send(packet);
// 关闭资源
socket.close();
}
}
package socketUDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPServer {
public static void main(String[] args) throws IOException {
//创建DatagramSocket传输接受对象
DatagramSocket socket = new DatagramSocket(9980);
//接收从客户端传来的数据并输出
byte[] myByte = new byte[128];
DatagramPacket packet = new DatagramPacket(myByte,myByte.length);
socket.receive(packet);
System.out.println(new String(packet.getData()));
//关闭资源
socket.close();
}
}
六.结束语
网络编程在没有学习的时候一直都是一知半解,只知道它大概就是个可以在不同计算机之间进行计算机通信的东西,但是具体是个怎么样的通信就不的而知了,这次的二刷还是了解到的不少的,把之前的TCP的传输是通过IO流来进行的,结合之前的笔记,在以前看来很难的东西现在慢慢的能知道要怎么做,为什么这么做了。