一、网络编程
1.为什么要有网络编程??
2.两个文件之间如何实现通信?
基于文件通信--两个程序都在同一台机器上
两个不同机器如何通信?
一个局域网的通信依靠交换机
网卡-mac-全球唯一
临时的地址:ip地址
ip网段:4位点分十进制:0.0.0.0-255.255.255.255 ip地址的范围 IPV4协议
同一网段:通过交换机;不同网段,通过路由器来找
交换机支持三种通信机制:广播、单播、组播
通过ip地址找到mac地址的过程--arp协议(广播,通过ip,满足条件的ip地址,单播回复mac地址)
mac地址是永久的唯一的
ip地址能够找到网络中的唯一一台机器
# 交换机是用于在一个局域网内的机器之间的通信
# 路由器是用于不同局域网之间的机器的通信
arp协议;一台机器通过ip地址和交换机找到另一台机器的mac地址的过程
ip地址能够找到网络中的唯一一台机器,临时的
如何在一台机器上精准的找到要和我通信的服务?
端口 0-65535 一般用8000以后的端口
在一台机器上 ,每一个服务所使用的端口不能相同
通过 ip+port 能够找到网络世界里的一个服务
两种通信协议:
TCP协议;全双工通信、高可靠性的通讯机制 三次握手 保证数据的完整性,不会在网络上丢失
四次挥手,,记住图。。抓包
UDP:速度快,不可靠的通信机制--qq、微信即时通信类的服务 可以加回执机制-实现了相对可靠
互联网协议,物理设备,掌握5层协议
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 为什么要有网络编程??? 2 # 两个文件之间如何实现通信? 3 # 基于文件通信 —— 两个程序都在同一台机器上 4 # 两个不同机器上的程序如何实现通信? 5 # 基于网络 6 7 # mac地址是永久的 唯一的 8 # 交换机是用于在一个局域网内的机器之间的通信 9 # 路由器是用于不同局域网之间的机器的通信 10 # arp协议:一台机器通过IP地址和交换机找到另一台机器的mac地址的过程 11 12 # ip地址能够找到网络中的唯一一台机器,临时的 13 14 # 如何在一台机器上精准的找到要和我通信的服务??? 15 # 端口 0-65535 8000—> 16 # 在一台机器上 每一个服务所使用的端口不能相同 17 18 # 通过什么能够找到网络世界里的一个服务? ip+端口 19 # 两种通信协议 20 # TCP、UDP 21 # 网络编程
互联网协议与osi模型
互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层
每层运行常见物理设备
每层运行常见的协议
二、socket
1.socket概念
socket(套接字)
tcp建立连接后,同一时刻不能和两个终端进行通信 2个whiletrue
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 3 sk=socket.socket() #拿到一个socket实例化对象 4 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) ##加入一条socket配置,重用ip和端口 5 sk.bind(('127.0.0.1',9000)) 6 sk.listen() #监听 7 while True:#无限的接电话 8 conn,addr = sk.accept() #等待来电 三次握手完毕 9 # print(addr) 10 # conn.send(b'hello') #发送数据 11 # print(conn.recv(1024)) #接收数据 12 while True: #接到电话之后无限聊 13 msg = input('>>>') 14 conn.send(msg.encode('utf-8')) # 发送数据 15 if msg == 'q': break 16 ret=conn.recv(1024).decode('utf-8') 17 if ret=='q':break 18 print(ret) 19 20 conn.close() 21 22 sk.close()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 sk=socket.socket() 3 4 sk.connect(('127.0.0.1',9000)) #元祖 5 6 # print(sk.recv(1024).decode('utf-8')) #接收一个数据,1024表示阻塞 最大接收1024个字节 7 # sk.send(b'byebye') 8 while True: 9 ret=sk.recv(1024).decode('utf-8') 10 if ret=='q':break 11 print(ret) 12 msg = input('client输入>>>') 13 sk.send(msg.encode('utf-8')) 14 if msg=='q':break 15 sk.close()
udp server发送要写地址,,,udp能够实现并发,能收到多个client收到的信息 1个whiletrue
tcp 不写参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 sk=socket.socket(type=socket.SOCK_DGRAM) 3 sk.bind(('127.0.0.1',8899)) 4 while True: 5 msg,addr=sk.recvfrom(1024) 6 print(addr,msg.decode('utf-8')) 7 inp = input('>>>') 8 #sk.sendto(b'byebye',addr) 9 sk.sendto(inp.encode('utf-8'),addr) 10 11 sk.close()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 sk=socket.socket(type=socket.SOCK_DGRAM) 3 while True: 4 inp=input('client>>>') 5 # sk.sendto(b'hello',('127.0.0.1',8899)) 6 sk.sendto(inp.encode('utf-8'),('127.0.0.1',8899)) 7 msg,addr=sk.recvfrom(1024) 8 print(msg.decode('utf-8')) 9 sk.close()
黏包:发送的两条数据,黏在了一起,只发生在tcp协议中
在连续send的过程中,就容易发生黏包现象
udp信息有长度限制(最大65535-ip头(20)-udp头(8)=65507个),tcp没有!
tcp协议的拆包机制 面向流的通信特点和Nagle算法 缓存
ftp上传下载文件
解决粘包问题:1.设置长度2.使用struct模块--无论多大,都能转成4位的
struct unpack返回只有一个元素的元祖,取值时取第一个元素即可,res[0]
书写发送字典的例子。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 import struct 3 sk = socket.socket() 4 sk.bind(('127.0.0.1',8080)) 5 sk.listen() 6 7 conn,addr = sk.accept() 8 inp = input('>>>').encode('utf-8') 9 inp_len = len(inp) 10 bytes_msg = struct.pack('i',inp_len) 11 conn.send(bytes_msg) 12 conn.send(inp) 13 conn.send(b'alex sb') 14 15 conn.close() 16 sk.close()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import socket 2 import struct 3 sk = socket.socket() 4 sk.connect(('127.0.0.1',8080)) 5 num = sk.recv(4) 6 num = struct.unpack('i',num)[0] 7 print(sk.recv(num)) 8 print(sk.recv(10)) 9 # dic = {'filename':'client','filesize':'os.path.getsize('路径')'} 10 # str_dic = json.dumps(dic).encode('utf-8') 11 # len(str_dic) 12 # struct.pack() 13 # dic_len = send(dic_len) 14 # send(str_dic) 15 sk.close()