网络编程
由于不同机器上的程序要通讯,才产生网络
c/s
B/S 手机端不适合
*统一入口
bs 和cs b/s 是c/s 架构一种
学完前端
广播和单播 是发送mac 地址 arp 协议
广域网 路由器
5000w 都恢复 广播风暴
网关 路由器 网关
# arp协议 : 通过IP地址获取某一台机器的mac地址
# 子网掩码
# 子网掩码 和 ip地址进行 按位 与 运算 就能得出一个机器所在的网段
# 网关地址 : 整个局域网中的机器能沟通过网关ip与外界通信
# 网段 : 子网掩码 和 ip地址进行 按位 与 运算
IP代表 你找到了电脑
# 端口 : 0-65535
#端口 找到的程式
在计算机上每一个需要网络通信的程序,都会开一个端口
在同一时间只会有一个程式占用一个端口
不可能在同一时间 有2个程式 占用同一个端口
《《《《《《《《《《《通过端口找程式
# 8000-酷狗音乐 22-ssh 3306-mysql
# python 网络应用 8000
# ip地址+端口号 : 在全网找到唯一的一台机器+唯一的应用
# 我们选择端口 : 8000之后
# tcp协议
# 全双工的通信协议 可靠的
# 一旦连接建立起来,那么连接两端的机器能够随意互相通信
# 面向连接的通信方式
# 数据安全不容易丢失
# 建立连接的 三次握手 ******
# 断开连接的 四次挥手 ****** 打电话
udp 快 发短信
自己努力 自己去想
127.0.0.1 本地回环地址
已注册公网IP
全世界通用传输层 选择通信协议
网络层 ip 协议
数据链路层 mac 地址 arp 协议
数据链路 网桥 网关 以太网交换器
物理层 集线器 双绞线 中继器
#socket 抽象层
是一个中间接口 尼操作网络接口
是一个模块 套接字
给予文件和网络
AF_INET 给予网络类型的套接字
写两个文件
socket
server
import socket
sk=socket.socket() #买手机
#避免服务器重启报错
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#sk.bind('ip','port') #绑定手机
sk.bind(('127.0.0.1',8081)) #绑定手机
sk.listen() #等待有人打电话
conn,addr=sk.accept() #接听电话 conn,addr 对面的地址
ret=conn.recv(1024) #听别人说话
print(ret)
conn.send(b'hello') #和别人说话
conn.close() #挂电话
sk.close() #关手机
client
##》》》4
import socket
sk=socket.socket() #买手机
sk.connect(('127.0.0.1',8081)) #拨别人号
sk.send(b'hi')
ret=sk.recv(1024)
print(ret)
sk.close()
改进版
#server
import socket
sk=socket.socket() #买手机
#避免服务器重启报错
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#sk.bind('ip','port') #绑定手机
sk.bind(('127.0.0.1',8081)) #绑定手机
sk.listen() #等待有人打电话
conn,addr=sk.accept() #接听电话 conn,addr 对面的地址
while 1:
ret=conn.recv(1024) #听别人说话
print(ret)
conn.send(b'hello') #和别人说话
ret=conn.recv(1024)
print(ret.decode('utf-8'))
conn.send(bytes("格拉条".encode('utf-8')))
conn.close() #挂电话
sk.close() #关手机
##有收必有发 收发必相等 send --- recv
##client
import socket
sk=socket.socket() #买手机
sk.connect(('127.0.0.1',8081)) #拨别人号
while 1:
sk.send(b'hi')
ret = sk.recv(1024)
print(ret)
sk.send(bytes("中午吃什么?".encode('utf-8')))
ret = sk.recv(1024)
print(ret.decode('utf-8'))
sk.close()
循环聊天
import socket
sk=socket.socket() #买手机
#避免服务器重启报错
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#sk.bind('ip','port') #绑定手机
sk.bind(('127.0.0.1',8081)) #绑定手机
sk.listen() #等待有人打电话
conn,addr=sk.accept() #接听电话 conn,addr 对面的地址
while 1:
ret=conn.recv(1024).decode("utf-8")
if ret=='bye':
break
print(ret)
info=input('>>>')
conn.send(bytes(info,encoding='utf-8'))
conn.close() #挂电话
sk.close() #关手机
##有收必有发 收发必相等 send --- recv
##client
import socket
sk=socket.socket() #买手机
sk.connect(('127.0.0.1',8081)) #拨别人号
while 1:
info=input(">>>")
sk.send(bytes(info,encoding='utf-8'))
ret = sk.recv(1024).decode("utf-8")
print(ret)
if ret=='bye':
sk.send(b'bye')
break
# sk.send(b'hi')
# ret = sk.recv(1024)
# print(ret)
# sk.send(bytes("中午吃什么?".encode('utf-8')))
# ret = sk.recv(1024)
# print(ret.decode('utf-8'))
sk.close()
长连接 不能同时和2个人聊天
udp
import socket
sk=socket.socket(type=socket.SOCK_DGRAM)#数据豹纹的
sk.bind(('127.0.0.1',8082))
#基于UDP
msg,addr=sk.recvfrom(1024)
print(msg.decode('utf-8'))
sk.sendto(b"bye",addr)
sk.close()
#不需要监听 也不需要建立连接
#在启动服务之后只能被动的等待客户端发送消息过来取
#客户端发送消息的同时 还会自带地址信息
#消息回复的时候 不仅需要发送信息 还需需要把对方的地址加上
#client
import socket
sk=socket.socket(type=socket.SOCK_DGRAM)
ip_port=('127.0.0.1',8082)
sk.sendto(b'hello',ip_port)
ret,addr=sk.recvfrom(1024)
print(ret.decode('utf-8'))
sk.close()
完善性质
import socket
sk=socket.socket(type=socket.SOCK_DGRAM)#数据豹纹的
sk.bind(('127.0.0.1',8083))
#基于UDP
while 1:
msg,addr=sk.recvfrom(1024)
print(msg.decode('utf-8'))
info = input("1>>>").encode('utf-8')
sk.sendto("1<<".encode('utf-8')+info,addr)
sk.close()
#聊一下午
import socket
sk=socket.socket(type=socket.SOCK_DGRAM)
ip_port=('127.0.0.1',8083)
while 1:
info=input("2>>")
info=('\033[34m 大哥的消息:%s \033[0m'%info).encode('utf-8')
sk.sendto(info, ip_port)
# sk.sendto("2<<".encode('utf-8')+info,ip_port)
ret,addr=sk.recvfrom(1024)
print(ret.decode('utf-8'))
sk.close()
执行操作系统的命令
import subprocess #可以分别拿到信息 os.popen()
res=subprocess.Popen("ipconfig",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) #放到管道里面
a=res.stdout.read().decode('gbk')
print(a)
基于udp 的时间同步
# 需求
# 写一个时间同步的服务器
# 服务端接收请求
# 按照client端发送的时间格式,将服务器时间转换成对应格式
# 发送给客户端
import time
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',9000))
while True:
msg,addr = sk.recvfrom(1024)
# msg 客户端发送给server端的时间格式 "%Y-%m-%d %H:%M-%S"
time_format = msg.decode('utf-8')
time_str = time.strftime(time_format)
sk.sendto(time_str.encode('utf-8'),addr)
sk.close()
#client
# client端每隔一段时间发送请求到服务端
# 发送时间的格式
import time
import socket
sk = socket.socket(type = socket.SOCK_DGRAM)
sk.sendto('%Y-%m-%d %H:%M:%S'.encode('utf-8'),('127.0.0.1',9000))
msg,addr = sk.recvfrom(1024)
print(msg.decode('utf-8'))
sk.close()
# 方式一
# 操作系统的定时任务 + python代码的形式
# 方式二
# while True + time.sleep的形式
基于tcp 远程执行命名
#service 下发命令
import socket
sk=socket.socket()
sk.bind(('127.0.0.1',8091))
sk.listen()
conn,addr=sk.accept()
conn.send(b'dir')
ret=conn.recv(1024).decode('utf-8')
print(ret)
conn.close()
sk.close()
#在client 端接收命令并执行
import socket
import subprocess #可以分别拿到信息
sk=socket.socket()
sk.connect(('127.0.0.1',8091))
cmd=sk.recv(1024).decode('gbk')
res=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) #放到管道里面
a="luxun"+(res.stdout.read()).decode('gbk')
sk.send(a.encode('utf-8'))
sk.close()
#执行自定义代码区快
import socket
import subprocess #可以分别拿到信息
sk=socket.socket()
sk.connect(('127.0.0.1',8091))
while 1:
cmd=sk.recv(1024).decode('gbk')
res=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) #放到管道里面
a="luxun"+(res.stdout.read()).decode('gbk')
sk.send(a.encode('utf-8'))
sk.close()
#service 下发命令
import socket
sk=socket.socket()
sk.bind(('127.0.0.1',8091))
sk.listen()
conn,addr=sk.accept()
while 1:
cmd=input("cmd:")
conn.send(cmd.encode("utf-8"))
ret=conn.recv(1024).decode('utf-8')
print(ret)
conn.close()
sk.close()
命令没接收完。或者接受多了 黏包现象
基于UDP的远程控制命令
import socket
sk=socket.socket(type=socket.SOCK_DGRAM)#数据豹纹的
sk.bind(('127.0.0.1',8083))
msg,addr=sk.recvfrom(10240)
while True:
cmd=input("cmd:")
sk.sendto(cmd.encode("utf-8"),addr)
msg,addr=sk.recvfrom(10240)
print(msg.decode("utf-8"))
sk.close()
#
import socket
import subprocess
sk=socket.socket(type=socket.SOCK_DGRAM)#数据豹纹的
addr=('127.0.0.1',8083)
sk.sendto("chile".encode('utf-8'),addr)
while 1:
cmd,addr=sk.recvfrom(10240)
res = subprocess.Popen(cmd.decode('gbk'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 放到管道里面
a = "luxun" + (res.stdout.read()).decode('gbk')
sk.sendto(a.encode('utf-8'),addr)
sk.close()
#udp 不会黏包 , 不可靠
tcp拆包机制 分发算法 算法优化