私有ip
私有ip就是局域网中使用的ip地址,国际规定有一部分ip地址是在局域网中使用的
私有ip的范围,也就是不在公网中使用的ip地址范围:
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255
4. 本机ip地址
127.0.0.1表示本机ip地址; 本机域名是localhost; 通过域名可以解析一个ip地址,域名方便大家记忆某台电脑的主机地址
Linux命令(ping, ifconfig)
查看或配置网卡信息:ifconfig
ifconfig查看网卡的信息:
测试远程主机连通性:ping
通常用ping来检测网络是否正常
2. 端口号
端口号:使用唯一一个编号来标识端口, 其实就是标识端口的一个编号。
在linux系统中,端口号有65536(2的16次方)个
- 端口号划分
端口号不是随意使用的,而是按照一定的规定进行分配。
端口号分为知名端口号和动态端口号
3.1 知名端口号(Well Known Ports)
知名端口号: 系统程序使用的端口号
知名端口号是众所周知的端口号,范围从0到1023
80端口分配给HTTP服务
21端口分配给FTP服务
一般情况下,如果一个程序需要使用知名端口的需要有root权限
3.2 动态端口号(Dynamic Ports)
动态端口号: 程序员开发应用程序使用端口号, 之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。
动态端口的范围是从1024到65535
当这个程序关闭时,同时也就释放了所占用的端口号
3.3 怎样查看端口号 ?
用 netstat -an 查看程序所使用的端口号
lsof -i [tcp/udp]:2425 查看端口号对应的应用程序
提示: 如果端口号找不到应用程序,使用管理员权限加上sudo
- 总结
网络通信的流程是先通过ip地址找到网络中的设备,再通过端口号来找到对应的端口,然后通过端口把数据传输给对应的应用程序
网络传输方式-UDP
1.UDP概念
UDP:英文全拼(User Datagram Protocol)简称用户数据报协议,它是无连接的、不可靠的网络传输协议
udp协议
udp网络传输协议好比现实生活中写信
udp协议
2.UDP特点
因为udp发送数据之前不需要建立连接所有具有以下特点
无连接
资源开销小
传输速度快
udp每个数据包最大是64K
3.UDP的优缺点
优点:
传输速度快
不需要连接,资源开销小
缺点:
传输数据不可靠,容易丢数据包
没有流量控制,当对方没有及时接收数据,发送方一直发送数据会导致缓冲区数据满了,电脑出现卡死情况,所有接收方需要及时接收数据。
4.UDP的使用场景
当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP
qq音视频传输,微信音视频传输
上课使用的共屏软件
发送广播消息
小结
UDP是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
socket介绍
目标
知道socket的作用
- 不同电脑上的进程之间如何通信
首先通过ip地址找到网络中对应的电脑,然后通过传输协议和端口号来确定这个进程(运行起来的软件),那么数据如何传输需要使用socket来完成,也就是进程之间通信使用socket
注意:
所谓进程指的是:运行的程序或者软件称之为进程(在讲解多任务编程时进行详细讲解)
所谓进程间通信指的是:运行的程序之间的数据共享
2. 什么是socket
socket(简称 套接字) 是进程间通信一个工具,它能实现把数据从一方传输到另外一方,完成不同电脑上进程之间的通信, 它好比数据的搬运工。
- socket使用场景
不夸张来说,只要跟网络相关的应用程序或者软件都使用到了socket, 比如:
socket使用场景1 socket使用场景1 socket使用场景1
小结
socket就是完成不同电脑上进程之间通信的一个工具,负责进程之间数据的传输
'192.168.1.103’表示目的ip地址
8080表示目的端口
dest_addr = (‘192.168.1.103’, 8080) # 注意 是元组,ip是字符串,端口是数字
-
从键盘获取数据
send_data = input(“请输入要发送的数据:”) -
发送数据到指定的电脑上的指定程序中
udp_socket.sendto(send_data.encode(‘utf-8’), dest_addr) -
关闭套接字
udp_socket.close()
在windows中运行“网络调试助手”:
网络调试助手接收数据
4.发送、接收数据
import socket
1. 创建udp套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
2. 准备接收方的地址
dest_addr = (‘192.168.236.129’, 8080)
3. 从键盘获取数据
send_data = input(“请输入要发送的数据:”)
4. 发送数据到指定的电脑上
udp_socket.sendto(send_data.encode(‘utf-8’), dest_addr)
5. 等待接收对方发送的数据
recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
6. 显示对方发送的数据
接收到的数据recv_data是一个元组
第1个元素是对方发送的数据
第2个元素是对方的ip和端口
print(recv_data[0].decode(‘gbk’))
print(recv_data[1])
7. 关闭套接字
udp_socket.close()
网络调试助手截图:
数据编码和解码
str->bytes:encode编码
bytes->str:decode解码
字符串通过编码成为字节码,字节码通过解码成为字符串。
text = ‘我是文本’
text
‘我是文本’print(text)
我是文本bytesText = text.encode()
bytesText
b’\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac’print(bytesText)
b’\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac’type(text)
<class ‘str’>type(bytesText)
<class ‘bytes’>textDecode = bytesText.decode()
textDecode
‘我是文本’print(textDecode)
我是文本
其中decode()与encode()方法可以接受参数,其声明分别为:
bytes.decode(encoding=“utf-8”, errors=“strict”)
str.encode(encoding=“utf-8”, errors=“strict”)
其中的encoding是指在解码编码过程中使用的编码格式,errors是指错误的处理方案。
注意:
errors=“strict”
strict:表示严格按照指定编解码方式进行编码和解码,如果编解码不成功则崩溃
ignore:表示忽略编解码不成功的字符,如果编解码不成功程序不会崩溃
udp绑定端口号
from socket import *
1. 创建套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)
2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配
local_addr = (’’, 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udp_socket.bind(local_addr)
3. 等待接收对方发送的数据
recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
4. 显示接收到的数据
print(recv_data[0].decode(‘gbk’))
5. 关闭套接字
udp_socket.close()
一个udp网络程序,不绑定端口号,此时操作系统会随机分配一个端口号,如果绑定端口号,每次启动程序端口号不变。
Python 中的 if name == ‘main’
[https://blog.csdn.net/qq_36775703/article/details/103433123]
import socket
if name == ‘main’:
# 创建udpsocket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 设置socket的选项,允许发送广播消息
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)
# 发送广播消息
udp_socket.sendto(“大家好,我叫小郭同学,多多关照!”.encode(“gbk”), (“255.255.255.255”, 9090))
# 关闭socket
udp_socket.close()
总结
广播地址最常用的是255.255.255.255
通过命令查看是否存在端口占用的问题。cmd下输入 netstat -ano|findstr 8080,找出8080端口对应的PID进程为4228。
输入tasklist |findstr 4228找出进程对应的详细信息。
解决办法:
(1)用taskkill pid的方式把不相关的进程关掉。
import socket
def send_msg(udp_socket):
“”“获取键盘数据,并将其发送给对方”""
# 1. 从键盘输入数据
msg = input("\n请输入要发送的数据:")
# 2. 输入对方的ip地址
dest_ip = input("\n请输入对方的ip地址:")
# 3. 输入对方的port
dest_port = int(input("\n请输入对方的port:"))
# 4. 发送数据
udp_socket.sendto(msg.encode(“utf-8”), (dest_ip, dest_port))
def recv_msg(udp_socket):
“”“接收数据并显示”""
# 1. 接收数据
recv_msg = udp_socket.recvfrom(1024)
# 2. 解码
recv_ip = recv_msg[1]
recv_msg = recv_msg[0].decode(“utf-8”)
# 3. 显示接收到的数据
print(">>>%s:%s" % (str(recv_ip), recv_msg))
def main():
# 1. 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 绑定本地信息
udp_socket.bind(("", 7890))
while True:
# 3. 选择功能
print("="*30)
print(“1:发送消息”)
print(“2:接收消息”)
print("="*30)
op_num = input(“请输入要操作的功能序号:”)
# 4. 根据选择调用相应的函数
if op_num == "1":
send_msg(udp_socket)
elif op_num == "2":
recv_msg(udp_socket)
else:
print("输入有误,请重新输入...")
if name == “main”:
main()
虚拟机网络 局域网与外网
TCp
网络传输方式-TCP
TCP:英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议.
2.TCP特点
- 面向连接
通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。
双方间的数据传输都可以通过这一个连接进行。
完成数据交换后,双方必须断开此连接,以释放系统资源。
这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。
- 可靠传输
TCP采用发送应答机制
TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功
超时重传
发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。
TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
错误校验
由发送端计算,然后由接收端验证,其目的是为了检测数据在发送端到接收端之间是否有改动,如果接收方检测到校验和有差错,则直接丢弃这个数据包。
流量控制和阻塞管理
流量控制用来避免主机发送得过快而使接收方来不及完全收下。
TCP和UDP区别
TCP面向连接; UDP是不面向连接;
TCP提供可靠的数据传输,也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP不保证可靠的数据传输,容易出现丢包情况;
TCP需要连接传输速度慢,UDP不需要连接传输速度快
TCP不支持发广播;UDP支持发广播
TCP对系统资源要求较多,UDP对系统资源要求较少。
TCP适合发送大量数据,UDP适合发送少量数据
TCP有流量控制,UDP没有流量控制
import socket
创建tcp socket
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
目的信息
server_ip = input(“请输入服务器ip:”)
server_port = int(input(“请输入服务器port:”))
链接服务器
tcp_client_socket.connect((server_ip, server_port))
提示用户输入数据
send_data = input(“请输入要发送的数据:”)
tcp_client_socket.send(send_data.encode(“gbk”))
接收对方发送过来的数据,最大接收1024个字节
recvData = tcp_client_socket.recv(1024)
print(‘接收到的数据为:’, recvData.decode(‘gbk’))
关闭套接字
tcp_client_socket.close()
如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务
client_socket用来为这个客户端服务
tcp_server_socket就可以省下来专门等待其他新客户端的链接
client_socket, clientAddr = tcp_server_socket.accept()
接收对方发送过来的数据
recv_data = client_socket.recv(1024) # 接收1024个字节
print(‘接收到的数据为:’, recv_data.decode(‘gbk’))
发送一些数据到客户端
client_socket.send(“thank you !”.encode(‘gbk’))
关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
client_socket.close()
tcp服务器一般情况下都需要绑定端口号,否则客户端找不到这个服务器
tcp客户端一般不绑定端口号,使用随机生成的端口号即可
tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
当tcp客户端和服务端建立好连接才可以收发数据,udp是不需要建立连接,直接就可以发送数据
当一个tcp客户端和服务端连接成功后,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
关闭accept返回的套接字意味着这个客户端已经服务完毕
当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线
tcp服务端绑定端口号,程序退出后端口号不会立即释放,解决办法可以设置socket选项,让程序退出端口号立即释放,也称为端口号复用
SYN: 表示连接请求 ACK: 表示确认 FIN: 表示关闭连接 seq:表示报文序号 ack: 表示确认序号
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack (number )=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送。
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1。
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送。
第四次挥手:Client收到FIN后,接着发送一个ACK给Server,确认序号为收到序号+1。
wireshark抓包工具使用
来源:CSDN
作者:qq_36775703
链接:https://blog.csdn.net/qq_36775703/article/details/103384822