网络编程
2018-09-15
1:软件开发的架构
两件程序之间通讯的应用大致可以分为两种:
第一种:qq. 微信,网盘,优酷 这一类是属于需要安装的桌面应用
第二种:比如百度, 知乎,博客园之类
c/s架构
即Client 与 Server, 客户端与服务器的端架构
b/s架构
Browser 与 Serverm 浏览器与服务端架构
IP地址
1: 网卡 :身份证 mac地址 计算机在网络上的身份证
2: 交换机 :负责一个网络内的多台机器之间的信息交换
3: mac地址 :16进制的数 全球唯一
1: 127.0.0.1 :本地回环地址 本机的地址
2: 0.0.0.0 : ip地址的、回环地址的所有的用户都能找到你这台机器
局域网
# 局域网
1: 网关ip 不同局域网之间通信依赖的ip地址
2: 子网掩码 判断两个ip地址是否在同一个网段内
3:网段
# 0.0.0.0 - 255.255.255.255
# 局域网的概念
# 外网ip 我们谁都能访问
# 内网ip 从外部不能访问,只能在内部环境中互相访问
# 外网ip永远不会和内网ip冲突?
# 0.0.0.0 - 255.255.255.255中间为内网保留了一些字段
# 192.168.0.0 - 192.168.255.255
# 10.0.0.0 - 10.255.255.255
# 172.16.0.0 - 172.31.255.255
局域网中两台机器的通信原理
局域网中两台机器的通信原理
# 交换机
# ip地址
# ip地址 -arp协议-> mac地址
# mac地址 : 全球唯一
# arp协议 : 广播 和 单播
# 通过ip地址获取mac地址
# 一台机器A发起一个arp请求(只包含ip地址),发送给交换机
# 交换机接收到请求,广播这条消息
# 所有的机器都会接收到这个请求,只有和要寻找ip地址吻合的机器B
# 才会回应交换机的广播,(带着自己的mac地址)
# 交换机通过单播的形式将回复的B的mac地址发送给A
# 判断两台机器是不是在同一个局域网内:
# 子网掩码
# A机器的ip地址和A的子网掩码 按位与
# B机器的ip地址和B的子网掩码 按位与
# 得到的结果如果一致 那么说明两台机器是在一个网段内的
端口
# 端口的概念 —— 帮助你找到一个应用
# 每一个网络服务都会占用计算机上的一个端口
# 计算机上的端口范围 0-65535
# 在同一时刻 同一台计算机上 不同的网络应用 占用的端口一定是不同的
2:OSI 七层模型
在7层的基础上简化为5层
# 应用层 http、https
# 传输层 TCP、UDP协议
# 端口 :找到某一台机器上的具体的网络应用
# tcp 面向连接 可靠 慢 全双工
# 三次握手 建立tcp连接的过程
# 发消息
# 四次挥手 断开tcp连接的过程
# udp 无连接 不可靠 快
# 网络层 ip协议
# 数据链路层 arp协议
# 物理层
Tcp 和 Udp
tcp 面向连接的 可靠的 但是慢
# tcp协议
# 两个应用之间要想通信 必须先建立连接
# 然后基于连接来通信
# 比较重要的文件 邮件的发送 下载安装包
udp 无连接的 快 能够发送的信息长度是有限的
# 快 但 不可靠 不能发送过长的数据
# 即时通讯类的程序
tcp和udp 的区别
tcp、udp是通过网络通信的两种方式
tcp 先建立连接再通信
# 可靠
# 慢
udp 不需要建立连接直接通信
# 快
# 不可靠
一个简单的tcp: server 和 client
sever
from socket import *
ip_port = ('127.0.0.1', 9514)
sk = socket(AF_INET, SOCK_STREAM)
sk.bind(ip_port)
sk.listen()
sk_cl, addr = sk.accept()
data1 = sk_cl.recv(10)
data2 = sk_cl.recv(10)
print('----->', data1.decode('utf-8'))
print('----->', data2.decode('utf-8'))
sk_cl.close()
client
from socket import *
ip_port = ('127.0.0.1', 9514)
sk = socket(AF_INET, SOCK_STREAM)
sk.connect(ip_port)
sk.send(b'my name is leiwenxuan')
sk.send(b'nsdfasfdsf')
udp的简单程序
sever
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1', 9000))
while 1:
msg,addr = sk.recvfrom(1024)
print(msg.decode('utf-8'), addr)
# sk.sendto('正在发送...'.encode('utf-8'), addr)
inp = input('input :')
client
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1', 9001))
while 1:
# sk.sendto('正在发送...'.encode('utf-8'), ('127.0.0.1', 9000))
inp = input('input:')
sk.sendto(inp.encode('utf-8'),('127.0.0.1', 9000) )
msg, addr = sk.recvfrom(1024)
print(msg.decode('utf-8'), addr[1])
一个重要的黏包处理
server
import json, struct
'''传输一个简单的文件'''
import os
from socket import *
path_name = r'G:\python笔记\Pythonjing\day31\video\1.内容回顾和作业讲解.mp4'
path_name = os.path.realpath(path_name)
size = str(os.path.getsize(path_name))
ip_port = ('127.0.0.1', 9514)
sk = socket(AF_INET, SOCK_STREAM)
sk.bind(ip_port)
sk.listen()
sk_cl, addr = sk.accept()
sk_cl.send(size.encode('utf-8'))
with open(path_name, 'rb') as f:
while 1:
data = f.read(2048)
pack_num = struct.pack('i', len(data))
sk_cl.send(pack_num)
sk_cl.send(data)
if not data:
pack_num = struct.pack('i', len(''))
sk_cl.send(pack_num)
print(len(data))
break
client
from socket import *
import struct
import sys
def processBar(num, total):
'''进度条'''
rate = num / total
rate_num = int(rate * 100)
if rate_num == 100:
r = '\r%s>%d%%\n' % ('|' * rate_num, rate_num,)
else:
r = '\r%s>%d%%' % ('|' * rate_num, rate_num,)
sys.stdout.write(r)
sys.stdout.flush
ip_port = ('127.0.0.1', 9514)
sk = socket(AF_INET, SOCK_STREAM)
sk.connect(ip_port)
size = int(sk.recv(1024).decode('utf-8'))
# processBar(2048, size)
num_size = 0
with open('lw.mp4','wb') as f:
while 1:
pack_num = sk.recv(4)
num = struct.unpack('i', pack_num)[0]
# print(num)
if not num:
break
ret = sk.recv(num)
f.write(ret)
num_size += num
processBar(num_size, size)