什么是网络
将一方的想要表达的内容通过传给另一方或者多方的工具,叫做网络。
网络是由节点和连线构成,表示诸多对象及其相互联系。在数学上,网络是一种图,一般认为专指加权图。网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型。在计算机领域中,网络是信息传输、接收、共享的虚拟平台,通过它把各个点、面、体的信息联系到一起,从而实现这些资源的共享。(摘自百度百科)
作用
将一方的想要表达的内容通过传给另一方或者多方,网络是信息传输、接收、共享的虚拟平台,通过它把各个点、面、体的信息联系到一起,从而实现这些资源的共享。
网络中的通信流程
通过IP找到网络上的设备,通过端口号找到端口,通过端口给应用提供数据。
怎样找到网络中的另一方?
地址,就像每个人都有家庭住址一样,在网路中也有地址,叫做 IP 地址,可以唯一标识一台设备。
IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。(摘自百度百科)
作用
就像通过地址可以找到你的家一样,通过 IP 地址可以找到网络上的另一个网络或者主机。
Window中使用 ipconfig
Window键 + R 打开运行,输入cmd 打开命令提示符,输入ipconfig 或者ipconfig -all 就能查看到信息了,默认是简略信息。
ipconfig … 显示信息
ipconfig /all … 显示详细信息
Linux中使用 ifconfig
Ctrl + T 打开终端,在终端中输入ifconfig 就能查看到信息了,默认是详细信息。
通过本地域名LocalHost 查看本机域名,可以检测网卡有没有问题
ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.016 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.023 ms
64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.026 ms
64 bytes from localhost (127.0.0.1): icmp_seq=5 ttl=64 time=0.037 ms
什么是端口
通过地址可以找到你的家(IP地址),但是想要进入你家的客厅(电脑中的应用程序),需要通过门厅(端口),然后才能进入客厅。端口就是数据通过的一扇门,或者一个通道,经过端口将数据提供给应用程序。
端口的作用
数据由端口传给应用,应用内的数据也可以由端口传出。
端口号
端口号分为知名端口号和动态端口号,范围分别是0-1024 、1024-65535 ,端口总数为 2**16(655356) 个,通过端口号可以找到端口,类似于通过门牌号可以找到你家。
查看端口使用情况
nanetstart -an …………查看端口使用情况
根据端口查找应用
sudo lsof -i [tcp/udp]:端口号 ……….根据端口号查找应用
什么是socket
网络中的数据从一方到另一方,其中数据的载体或者运输工具就是socket。socket 将从应用中传出的数据通过物理链路传输到接收方的应用程序中,所以可以说socket 网络上不同电脑上的进程之间通信的工具。
基本步骤
import socket
def main():
# 创建udp 传输协议的socket ,通过socket 模块创建Socket 类的对象,
# 并传值socket.AF_INET(ip协议类型 ipv4),socket.SOCK_DGRAM(传输协议类型 udp协议)
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 数据,字符串编码成二进制数据,编码格式根据接收方编码决定
# window 系统默认GBK 编码,Linux 系统默认UTF-8 编码,
# Python3 encode() decode() 默认编码格式为UTF-8
data = "DragonFang 到此一游".encode("gbk")
# 接收方的IP 以及端口号 ,元组类型
dest_ip_port = ("192.168.13.14", 5210)
# udp socket发送数据使用sendto() 方法,方法需要传值
# data 二进制数据;dest_ip_port 收方的IP 以及端口号,元组类型
udp_socket.sendto(data, dest_ip_port)
while True:
# 如果需要接收数据recvfrom() 方法;参数 1024,接收数据长度为1024 个字节,超过长度的数据丢失
# Window 超过长度报错10040 未解决,双方约定长度可以临时解决
recv_data, recv_ip_port = udp_socket.recvfrom(1024)
recv_content = recv_data.decode("gbk", errors="ignore")
print(recv_content)
if not recv_data:
break
# 使用完成关闭
udp_socket.close()
if __name__ == '__main__':
main()
decode() 的参数errors 有三个值,
# 源码
def decode(self, input, errors='strict'):
if errors not in ('strict', 'replace', 'ignore'):
raise UnicodeError("Unsupported error handling "+errors)
res = punycode_decode(input, errors)
return res, len(input)
# 测试 errors="replace" 与 errors="ignore" 区别
# data = "你猜".encode("gbk")
# print(data)
# gbk_con = data[0:3].decode("gbk", errors="ignore")
# gbk_con_re = data[0:3].decode("gbk", errors="replace")
# print("gbk_con", gbk_con, "end")
# print("gbk_con_re", gbk_con_re, "end")
#
# gbk_con = data[3:].decode("gbk", errors="ignore")
# gbk_con_re = data[3:].decode("gbk", errors="replace")
# print("gbk_con", gbk_con, "end")
# print("gbk_con_re", gbk_con_re, "end")
什么是传输协议
传输协议中各层都为上一层提供业务功能。为了提供这种业务功能,下一层将上一层中的数据并入到本层的数据域中,然后通过加入报头或报尾来实现该层业务功能,该过程叫做数据封装。用户的数据要经过一次次包装,最后转化成可以在网络上传输的信号,发送到网络上。当到达目标计算机后,再执行相反的拆包过程。这类似于日常生活中写信,把自己要表达的意思写到纸上,有兴趣的话还要把纸折叠成特殊的形状,然后放到信封里并封好口,写好收信人的地址、邮政编码和姓名,再贴上邮票,邮局的工作人员再盖上邮戳送到收信人所在邮局,邮递员按信上的地址把信交给收信人,收信人再拆信,阅读其内容。(摘自百度百科)
用户数据包协议,当传输出现错误时会将错误信息丢弃
udp socket
基本步骤
import socket
def main():
# 使用udp 传输协议创建socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 准备数据
data = "DragonFang 到此一游".encode("gbk")
# 接收方的IP 以及端口号 ,元组类型
dest_ip_port = ("192.168.13.14", 5210)
# 发送数据
udp_socket.sendto(data, dest_ip_port)
while True:
# 接收数据
recv_data, recv_ip_port = udp_socket.recvfrom(1024)
# 解码收到的二进制数据
recv_content = recv_data.decode("gbk", errors="ignore")
print(recv_content)
# 接收到的数据长度为0,退出循环
if not recv_data:
break
# 使用完成关闭
udp_socket.close()
if __name__ == '__main__':
main()
传输控制协议,当传输出现错误时能自动予以纠正
tcp client socket
基本步骤
import socket
def main():
# 创建tcp 传输协议的socket ,通过socket 模块创建Socket 类的对象,
# 并传值socket.AF_INET(ip协议类型 ipv4),socket.SOCK_STREAM(传输协议类型 tcp协议)
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务端ip 服务端端口号,元组类型
server_ip_port = ("192.168.109.1", 8080)
# 建立连接
tcp_client_socket.connect(server_ip_port)
# 数据
data = "DragonFang 到此一游".encode("gbk")
# 发送数据
tcp_client_socket.send(data)
while True:
# 接收数据,超过接收长度,本次不接收,下次再接收;参数 1024,接收数据长度为1024 个字节
sever_data = tcp_client_socket.recv(12)
# 解码数据
sever_content = sever_data.decode("gbk", errors="ignore")
# 二进制数据为0 ,退出
if not sever_data:
print("退出")
break
# 关闭连接
tcp_client_socket.close()
if __name__ == '__main__':
main()
tcp server socket
基本步骤
import socket
def main():
# 创建tcp 传输协议的socket ,通过socket 模块创建Socket 类的对象,
# 并传值socket.AF_INET(ip协议类型 ipv4),socket.SOCK_STREAM(传输协议类型 tcp协议)
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务端ip 服务端端口号,元组类型 ;ip 缺省,用于适应多个IP 地址的情况
server_ip_port = ("", 8080)
# 绑定端口号
tcp_server_socket.bind(server_ip_port)
# 监听建立连接的请求;参数128 最大等待连接数
tcp_server_socket.listen(128)
# 建立连接
tcp_client_socket, client_ip_port = tcp_server_socket.accept()
while True:
# 接收数据
client_data = tcp_client_socket.recv(1024)
# 解码数据 ,解码方式与客户端编码方式相同
client_content = client_data.decode("gbk", errors="ignore")
if not client_data:
break
# 数据
data = "DragonFang 到此一游".encode("gbk")
# 发送数据
tcp_client_socket.send(data)
# 关闭客户端socket ,断开与客户端的连接
tcp_client_socket.close()
# 关闭服务器socket,不再接收连接请求
tcp_server_socket.close()
if __name__ == '__main__':
main()
面向连接
可靠性
内容形式
服务形式
资源占用
逻辑信道
传输速度
适用场景
TCP建立连接时发生,三次握手(three times handshake;three-way handshake)所谓的“三次握手”即对每次发送的数据量是怎样跟踪进行协商使数据段的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送、接收完毕后何时撤消联系,并建立虚连接。(摘自百度百科)
过程 (摘自百度百科)
个人理解:一次完整握手礼的不同步骤,我伸出手,对方伸出手,两手相握,握手礼完成
我伸出手
TCP第一次握手,我见到朋友(建立连接),伸出我的手(发送syn包到服务器,进入SYN_SENT状态),等待朋友作出反应(等待服务器确认)
对方伸出手
TCP第二次握手,朋友看到我伸出手(收到syn包),明白这是要握手(确认客户的SYN),很给面的伸出了手(发送SYN+ACK包到客户端,服务器进入SYN_RECV状态)
两手相握
TCP第三次握手,我看到朋友很给面的伸出了手(收到服务器的SYN+ACK包),我主动迎上去(发送确认包ACK),两手相遇,紧紧地握在一起(TCP连接成功),兄弟情深。。。。
TCP关闭连接的步骤如下: (摘自百度百科)
理解:
第四次挥手,客户端收到FIN后,接着发送一个ACK给服务端,服务端关闭,但是客户端会监听服务端端口,看服务端是否会再次请求数据,造成服务端端口被占用。
到此结 DragonFangQy 2018.4.21
发送长度大于接收长度,Window 报错10040 未解决,双方约定长度可以临时解决
udp_socket.recvfrom(1024)