python 网络通信
目录
- 一、ip 地址
- 1、ip 地址的分类
- A类
- B 类
- C 类
- 私有地址
- 公有地址
- 特殊 ip
- 二、端口 port
- 1、知名端口
- 2、动态端口
- 三、udp 通信
- 1、socket
- 2、bind 绑定
- 3、网络通信过程
- 4、udp 聊天室
- 5、udp 广播
- 四、tcp 通信
- 1、对比 udp
- 2、特点
- 3、tcp 客户端
- 4、tcp 服务器
- 5、文件下载器
- 6、tcp 的三次握手
- 7、tcp 的四次挥手
一、ip 地址
- 作用:电脑的唯一标记,不能重复
- dest ip: 目的 ip
- srp: 源 ip
1、ip 地址的分类
- ipv4:192.168.14.60
- ipv6:fe80::250::56ff:fe32:8cd0/64
A类
- 网络号:192.168.14
- 主机号:60
B 类
- 网络号:192.168
- 主机号:14.60
C 类
- 网络号:192
- 主机号:168.14.60
私有地址
不能上互联网
公有地址
能直接上网
特殊 ip
- 127.0.0.1~127.255.255.255用于回路测试
- 127.0.0.1可以代表本机IP地址
二、端口 port
- 进出网络程序的通道
- 用端口号标记电脑上运行的程序
- 整数,0~65535
- 进程:运行中的程序
1、知名端口
- 特殊程序
- 0~1023
- 22:ssh 远程登陆 Linux 系统
- 80:网站一般用的端口
- 69:下载文件
2、动态端口
- 普通程序
- 1024~65535
- 查看端口状态
- netstat - t/u
三、udp 通信
- 用户数据报协议
- 快速
- 易丢失
1、socket
- 协议:传送数据的格式
- udp:只负责发送,不管是否被接收
- tcp:每发送一个数据,接收方需回送一个响应
import socket
# 创建 udp 套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # ipv4, udp
# 获取需要发送的数据
msg = input("输入要发送的数据:")
# 发送数据
s.sendto(msg.encode("utf-8"), ("ip", 8080)) # 内容,(ip, 端口)
# 接收数据并打印
recv_msg = s.recvfrom(1024) # 堵塞,若没有接收到数据,卡在这个位置
print("%s(%d)>>>%s" % (recv_msg[1][0], recv_msg[1][1], recv_msg[0].decode("utf-8"))) # gbk
# 关闭套接字
s.close()
2、bind 绑定
- 固定端口
- 发送信息之前
# 绑定一个 ip 和端口
local_info = ("ip", 7788) # 本地信息
s.bind(local_info)
3、网络通信过程
4、udp 聊天室
import socket
def send_msg(s):
# 获取发送的数据
send_content = input("输入发送的内容:")
# 获取对方 ip
send_ip = input("目标 ip:")
# 获取对方端口
send_port = int(input("目标端口:"))
# 发送数据
s.sendto(send_content.encode("utf-8"), (send_ip, send_port))
def recv_msg(s):
recv_content, client_info = s.recvfrom(1024)
print(">>>%s(%s):%s" % (client_info[0], client_info[1], recv_content.decode("utf-8")))
def main():
# 创建套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定
s.bind(("", 7890))
# 功能选择
while True:
print("1: 发送数据")
print("2: 接收数据")
print("3: 退出")
op = input("要进行的操作序号:")
if op == "1":
send_msg(s)
elif op == "2":
recv_msg(s)
elif op == "3":
break
s.close()
if __name__ == '__main__':
main()
5、udp 广播
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
四、tcp 通信
- 传输控制协议
- 稳定,很少丢失
- 较慢
1、对比 udp
- 需要先建立链接
- TCP 每次发送一个数据包,对方都要确认,保证数据准确到达对方
- TCP 通信过程中,通道占用
- TCP 只需要建立一次链接
2、特点
- 面向连接,无法广播
- 发送-应答机制
- 超时重传
- 错误校验
- 流量控制和阻塞管理
3、tcp 客户端
import socket
# 创建 tcp 套接字
client_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ipv4, tcp
# 链接服务器
client_s.connect(("ip", 8080))
# 发送数据
client_s.send("hello world".encode("utf-8"))
# 关闭套接字
client_s.close()
- 发送、接收数据:
4、tcp 服务器
- 为别的软件提供服务的软件
- 服务器一般都需要绑定
- 客户端一般不绑定
import socket
# 创建 tcp 套接字
server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建的套接字是用来等待客户端链接用的
# 绑定本地信息
server_s.bind(("", 7890))
# 将套接字由主动链接模式改为被动模式
server_s.listen(128)
# 等待客户端的链接
# accept 返回的套接字用来与客户端通信
new_s, client_info = server_s.accept() # 默认堵塞,直到一个 tcp 客户端链接之后解除
print(client_info)
# 接收/发送数据
while True:
recv_content = new_s.recv(1024) # 若 recv 解堵塞,说明:客户端发过来数据/客户端关闭了通信。若收到的数据长度为 0,意味着断开了链接
if len(recv_content) != 0:
print(recv_content)
else:
new_s.close()
break
server_s.close()
5、文件下载器
- 客户端:
import socket
# 创建 tcp 套接字
client_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 链接 tcp 服务器
server_ip = input("输入服务器的 ip:")
server_port = int(input("输入服务器的端口:"))
client_s.connect((server_ip, server_port))
print("链接服务器(%s)成功" % server_ip)
# 发送要下载的文件的名字的字符串
download_file_name = input("输入要下载的文件的名字")
# recv 接收
client_s.send(download_file_name.encode("utf-8"))
# 存储
content = client_s.recv(1024)
print("接收到的数据:")
print(content.decode("gbk"))
# 将数据存储到一个文件中
with open(download_file_name, "w") as f:
f.write(content.decode("gbk"))
print("下载文件(%s)成功" % download_file_name)
# 关闭套接字
client_s.close()
- 服务器:
import socket
# 创建 tcp 套接字
server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定本地信息
port = 7890
server_s.bind(("", port))
# 监听模式
server_s.listen(128)
print("等待客户端链接,端口:%d" % port)
# 等待客户端链接
new_s, client_info = server_s.accept()
print("已经链接(%s)" % str(client_info))
# 接收客户端要下载的文件字
download_file_name = new_s.recv(1024).decode("utf-8")
# 找到文件名,读取内容
with open(download_file_name, "r") as f:
content = f.read()
# 将数据发送给客户端
new_s.send(content.encode("gbk"))
# 关闭套接字
new_s.close()
server_s.close()
6、tcp 的三次握手
通信双方建立链接的过程。
- 从客户端调用 connect 开始。客户端自动发送一个SYN数据给对方,包中有一个数字,开始3次握手
- 服务器接收到该SYN数据包,将数字+1,会送。(ACK+SYN)
- 客户端接收到后,数值+1,回送给tcp
- 最终目的:双方都明确对方存在,而且都准好了资源
7、tcp 的四次挥手
- 最终目的:释放资源
- 单工:收音机
- 半双工:对讲机
- 全双工:手机、网络