我是靠谱客的博主 重要台灯,这篇文章主要介绍【TCPIP协议】lipp_chan学习笔记一、原理二、应用,现在分享给大家,希望可以做个参考。

一、原理

在这里插入图片描述
在这里插入图片描述

1.IP协议(Internet protocol)

IP协议的作用在于把各种数据包准备无误的传递给对方,其中两个重要的条件是IP地址和MAC地址。由于IP地址是稀有资源,不可能每个人都拥有一个IP地址,所以我们通常的IP地址是路由器给我们生成的IP地址,路由器里面会记录我们的MAC地址。而MAC地址是全球唯一的。举例,IP地址就如同是我们居住小区的地址,而MAC地址就是我们住的那栋楼那个房间那个人。IP地址采用的IPv4格式,目前正在向IPv6过渡。
其中IP地址分为网络地址和主机地址,每个机器可能有相同的主机地址,但是网络地址取决你接入组织的IP地址,通过NAT你可以将主机地址转换成网络地址

例子:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获得本地主机IP地址对象 InetAddress inet01 = InetAddress.getLocalHost(); // 主机名/ip地址字符串 System.out.println(inet01); // 根据IP地址字符串或主机名获得对应的IP地址对象 InetAddress inet02 = InetAddress.getByName("www.baidu.com"); System.out.println(inet02); // 获得主机名 String hostName = inet01.getHostName(); System.out.println(hostName); // 获得IP地址字符串 String hostAddress = inet01.getHostAddress(); System.out.println(hostName); System.out.println(hostAddress);
复制代码
1
2
3
4
5
6
7
value: LTCN001705/10.225.114.108 www.baidu.com/180.101.49.11 LTCN001705 LTCN001705 10.225.114.108

2.TCP协议(Transmission Control Protocol)

TCP(传输控制协议)是面向连接的传输层协议。TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。TCP协议采用字节流传输数据。
  传输层起着承上启下的作用,涉及源端节点到目的端节点之间可靠的信息传输。传输层需要解决跨越网络连接的建立和释放,对底层不可靠的网络,建立连接时需要三次握手,释放连接时需要四次挥手。 
在这里插入图片描述
源端口:两个字节。端口用于寻找发送端和接收端的进程,通过端口号和IP地址,可以确立唯一一个TCP链接。
序号:SEq序号,用于标识TCP发送端到TCP接收端发送的数据字节流。
确认序号:认序号应该是上次已经成功收到数据字节序号加1,即Ack=Seq + 1。
SYN(同步):在连接建立时用来同步序号
ACK(确认):为1时表明确认号字段有效
PSH(推送):为1时接收方应尽快将这个报文段交给应用层
RST(复位):为1时表明TCP连接出现故障必须重建连接
FIN(终止):为1时表明发送端数据发送完毕要求释放连接

3.TCP三次握手和四次挥手

在这里插入图片描述
连接建立–>数据传送–>连接释放
tcp连接采用cs方式
第一次握手(客户端发送请求)
客户机发送连接请求报文段到服务器,并进入SYN_SENT状态,等待服务器确认。发送连接请求报文段内容:SYN=1,seq=x;SYN=1意思是一个TCP的SYN标志位置为1的包,指明客户端打算连接的服务器的端口;seq=x表示客户端初始序号x,保存在包头的序列号(Sequence Number)字段里。
第二次握手(服务端回传确认)

服务器收到客户端连接请求报文,如果同意建立连接,向客户机发回确认报文段(ACK)应答,并为该TCP连接分配TCP缓存和变量。服务器发回确认报文段内容:SYN=1,ACK=1,seq=y,ack=x+1;SYN标志位和ACK标志位均为1,同时将确认序号(Acknowledgement Number)设置为客户的ISN加1,即x+1;seq=y为服务端初始序号y。

第三次握手(客户端回传确认)

客户机收到服务器的确认报文段后,向服务器给出确认报文段(ACK),并且也要给该连接分配缓存和变量。此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。客户端发回确认报文段内容:ACK=1,seq=x+1,ack=y+1;ACK=1为确认报文段;seq=x+1为客户端序号加1;ack=y+1,为服务器发来的ACK的初始序号字段+1。
    注意: 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
    TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
在这里插入图片描述

1. TCP客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态。发送报文段内容:FIN=1,seq=u;FIN=1表示请求切断连接;seq=u为客户端请求初始序号。

2. 服务端收到这个FIN,它发回一个ACK给客户端,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号;服务端进入CLOSE_WAIT状态。发送报文段内容:ACK=1,seq=v,ack=u+1;ACK=1为确认报文;seq=v为服务器确认初始序号;ack=u+1为客户端初始序号加1。

3. 服务器关闭客户端的连接后,发送一个FIN给客户端,服务端进入LAST_ACK状态。发送报文段内容:FIN=1,ACK=1,seq=w,ack=u+1;FIN=1为请求切断连接,ACK=1为确认报文,seq=w为服务端请求切断初始序号。

4. 客户端收到FIN后,客户端进入TIME_WAIT状态,接着发回一个ACK报文给服务端确认,并将确认序号设置为收到序号加1,服务端进入CLOSED状态,完成四次挥手。发送报文内容:ACK=1,seq=u+1,ack=w+1;ACK=1为确认报文,seq=u+1为客户端初始序号加1,ack=w+1为服务器初始序号加1。

4.为什么是三次握手而四次挥手

多了一个FIN来告诉客户端,确认结束链接

5.UDP协议

DatagramPacket

UDP的数据包对象。

发送端:

复制代码
1
2
`DatagramPacket(byte[] buf, int length, InetAddress address, int port)`
复制代码
1
2
3
4
5
buf是要发送的内容,字节数组。 length是发送内容的长度,单位是字节。 address是接收端的IP地址对象 port是接收端的端口号。

接收端:

用于创建接收端的数据包对象

复制代码
1
2
DatagramPacket(byte[] buf, int length)
复制代码
1
2
3
buf:用来存储接收到内容。 length:能够接收内容的长度

DategramSocket

DatagramSocket()创建发送端的Socket对象,系统随机分配一个port号
DatagramSocket(int port) :创建接收端的Socket对象并指定端口号

例子

发送端代码

6.TCP与UDP的区别

  • TCP基于连接,UDP无连接。
  • TCP保证数据正确性,UDP可能丢包

7.HTTP协议

HTTP是应用层协议,基于TCP协议的请求响应协议。
http请求和响应报文都是由请求行、首部行和实体主体组成,其中分别为请求报文格式:
在这里插入图片描述
响应报文格式
在这里插入图片描述

常见状态码

在这里插入图片描述

HTTPS

安全版的HTTP,HTTPS的安全基础就是ssl,HTTP协议不适合传输一些敏感信息,比如信用开号、密码等。http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的;https协议是有ssl+http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

8.为什么f12的网络信息为空。

右边设置改为默认就行

二、应用

Socket

1.原理

Socket,套接字,就是两台主机之间逻辑连接的端点。TCP、IP是传输层协议,解决数据在网络中传输问题。HTTP是应用层协议,主要解决包装数据的问题。Socker是通信的基石,包含网络通信必须的五种信息:1.连接使用的协议、2.本地主机IP地址、3.本地机型的协议端口、远程主机的IP地址、远程进程的协议端口。socket是对端口通信开发的工具,它要更底层一些。传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.例子

一对一

client
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class SocketClient { public static void main(String[] args) throws UnknownHostException, IOException { int port = 7000; String host = "localhost"; // 创建一个套接字并将其连接到指定端口号 Socket socket = new Socket(host, port); DataInputStream dis = new DataInputStream( new BufferedInputStream(socket.getInputStream())); DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(socket.getOutputStream())); Scanner sc = new Scanner(System.in); boolean flag = false; while (!flag) { System.out.println("请输入正方形的边长:"); double length = sc.nextDouble(); dos.writeDouble(length); dos.flush(); double area = dis.readDouble(); System.out.println("服务器返回的计算面积为:" + area); while (true) { System.out.println("继续计算?(Y/N)"); String str = sc.next(); if (str.equalsIgnoreCase("N")) { dos.writeInt(0); dos.flush(); flag = true; break; } else if (str.equalsIgnoreCase("Y")) { dos.writeInt(1); dos.flush(); break; } } } socket.close(); } }
server
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package day614; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class SocketServer { public static void main(String[] args) throws IOException { int port = 7000; ServerSocket serverSocket = new ServerSocket(port); Socket socket = serverSocket.accept(); DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream())); DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); System.out.println("Start================="); do { double length = dis.readDouble(); System.out.println("服务器端收到的边长数据为:" + length); double result = length * length; dos.writeDouble(result); dos.flush(); } while (dis.readInt() != 0); System.out.println("运行结束"); socket.close(); serverSocket.close(); } }

一对多,使用多线程套在服务器上

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package day614; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SocketServerM { public static void main(String[] args) throws IOException { int port = 7000; int clientNo = 1; ServerSocket serverSocket = new ServerSocket(port); // 创建线程池 ExecutorService exec = Executors.newCachedThreadPool(); try { while (true) { Socket socket = serverSocket.accept(); exec.execute(new SingleServer(socket, clientNo)); clientNo++; System.out.println(clientNo); } } finally { serverSocket.close(); } } } package day614; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; public class SingleServer implements Runnable { private Socket socket; private int clientNo; @Override public void run() { // TODO Auto-generated method stub try { DataInputStream dis = new DataInputStream( new BufferedInputStream(socket.getInputStream())); DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(socket.getOutputStream())); do { double length = dis.readDouble(); System.out.println("从客户端" + clientNo + "接收到的边长数据为:" + length); double result = length * length; dos.writeDouble(result); dos.flush(); } while (dis.readInt() != 0); } catch (IOException e) { e.printStackTrace(); } finally { System.out.println("与客户端" + clientNo + "通信结束"); try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public SingleServer(Socket socket, int clientNo) { this.socket = socket; this.clientNo = clientNo; } }

3.对象类讲解

Socket(String host, int port):根据ip地址字符串和端口号创建客户端Socket对象
OutputStream getOutputStream():获得字节输出流对象。
InputStream getInputStream():获得字节输入流对象。

复制代码
1
2
ServerSocket一个该类的对象就代表一个服务器端程序。

在socket通信方式中,服务器是主动等待连接通信的到来。
利用socket进行通信时,服务器端的程序可以打开多个线程与多个客户进行通信,还可以通过服务器使各个客户之间进行通信。这种方式比较灵活,适用于一些较复杂的通信,但是服务器端的程序必须始终处于运行状态以监听端口。
利用 URL进行通信时,服务器端的程序只能与一个客户进行通信,形式比较单一。但是它不需要服务器端的CGI程序一直处于运行状态,只是在有客户申请时才被激活。所以,这种方式比较适用于客户机的浏览器与服务器之间的通信。
总之,Socket是底层实现,协议你要自己去写,不局限于http,可以是任何协议。而类似HttpClient, FtpClient,URLConnetcion之类的,是对专属协议的封装,当然由于部分实现原理,你可能无法完全控制连接操作,比如setTimeout这个参数。

最后

以上就是重要台灯最近收集整理的关于【TCPIP协议】lipp_chan学习笔记一、原理二、应用的全部内容,更多相关【TCPIP协议】lipp_chan学习笔记一、原理二、应用内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(91)

评论列表共有 0 条评论

立即
投稿
返回
顶部