python网络编程总结
目录
网端总结
网络基本知识
IP协议
- IP协议一般指IP。IP是Internet Protocol(网际互连协议)的缩写,是TCP/IP体系中的网络层协议
- ip地址:可以识别到某一台具体的计算机,port(端口):可以找到计算机中确定的服务应用(app等)
- 在window中查看本机的ip配置信息在cmd中输入ipconfig
ipv4协议
- ipv4协议是由32位2进制组成的四位点分十进制(如255.255.255.255)
ipv6协议
- ipv6协议是由128位2进制组成的八位冒分16进制,分为三种
- 内嵌ipv4法:X:X:X:X:X:X:d.d.d.d
- 冒分十六进制表示法:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
- 0位压缩表示法:FF01:0:0:0:0:0:0:1101 → FF01::1101
mac地址
- 以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的地址。在OSI模型中,第三层网络层负责IP地址,第二层数据链路层则负责MAC位址。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址
- MAC地址的长度为48位(6个字节),通常表示为12个16进制数,如:00-16-EA-AE-3C-40就是一个MAC地址,其中前6位16进制数00-16-EA代表网络硬件制造商的编号,它由IEEE(电气与电子工程师协会)分配,而后6位16进制数AE-3C-40代表该制造商所制造的某个网络产品(如网卡)的系列号
- 在命令提示符下输入命令“ipconfig /all”回车之后就会显示当前计算机的一些网络信息,其中“Physical Address”字样的这一项就是当前计算机中网卡的 MAC地址。当然,如果计算机中安装有多个网卡,则会有多个“Physical Address”字样
局域网内部通信
- 局域网内部通信主要通过交换机
- 交换机只能识别mac地址(一般内部有交换标签,将每台机器的IP地址对应机器的mac地址),交换机具有单播,广播和组播的功能
- 其中设计的协议为arp协议:地址解析协议,能通过ip地址找到具体的mac地址
局域网之间通信
- 局域网之间通信主要通过路由器
- 路由器可以识别ip地址(里面有路由表,每个网关对应一个网段,一个网段就是一个局域网(子网))
- 其中设计的协议就是ip协议
- 子网掩码:32位2进制,255.255.255.0。用来判断两台机器是否在同一网段中
- 通过与IP地址进行位与计算来判断
网段
内网ip地址
- 保留字段
- 192.168.0.0-192.168.255.255
- 172.16.0.0-172.31.255.255
- 10.0.0.0-10.255.255.255
- 小型企业或家庭网络可以选择192.168.0.0,大中型企业网络可以选择172.16.0.0或10.0.0.0地址段
公网ip地址
- 公网地址是指在因特网上直接可达的地址,如果你有一个公网地址,那就意味着你不但能访问别人,还能被人访问,一般需要申请购买
本地回环地址
- 127.0.0.1:过网卡不过交换机找自己,一般是做测试时使用
网络开发架构
C/S架构
- C/S(client/server 客户端与服务端),这种架构需要下载相应的程序,如app等才能使用
- 特点:可离线使用/功能完善/安全性能高
B/S架构
- B/S(broswer/server 浏览器端与服务端),这种架构不需要下载对应的应用,只需在浏览器中输入对应的网址即可
- 特点:无需下载/统一了用户端输入路径/安全性比C/S低
OSI七层/五层/四层协议
OSI五层协议
层数 | 层名 | 物理设备 | 协议 |
---|---|---|---|
第一层 | 物理层 | / | / |
第二层 | 数据链路层 | 交换机,网卡 | arp协议 |
第三层 | 网络层 | 三次交换机/路由器 | ip协议 |
第四层 | 传输层 | 四层交换机/四层路由器 | TCP/UDP协议 |
第五层 | 应用层 | / | http协议 |
OSI七层协议
- 应用层/表示层/会话层/传输层/网络层/数据链路层/物理层
OSI四层协议
- 应用层传输层/网络层/网络接口层
TCP/UDP
TCP
- TCP(Transmission Control Protocol 传输控制协议)可靠的,面向连接的协议
- 特点:占用连接/实时性强/可靠/传输效率低/全双工通信
- 应用:qq视频/下载高清电影/发邮件等
- 建立连接:三次握手
- 第一次握手是客户端向服务端发送请求连接SYN信号
- 第二次握手是服务端向客户端发送ACK应答信号+SYN请求连接信号
- 第三次握手是客户端向服务端发送ACK应答信号,这时双方建立网络连接
- 断开连接:四次挥手
- 第一次挥手是客户端向服务端发送FIN断开连接请求信号
- 第二次挥手是服务端向客户端发送ACK应答信号,客户端向服务端的通信路断开连接
- 服务端向客户端发送FIN断开连接请求信号
- 第三次挥手是客户端向服务端发送ACK应答信号,服务端向客户端的通信路断开连接
UDP
- udp(User Datagram Protocol 用户数据报协议),这是一种无需建立连接的协议
- 特点:不占用连接/不可靠
- 应用:发短信/在线播放视频/qq短信
Socket模块
TCP通信
#server端代码
import socket
s=socket.socket()
s.bind(('127.0.0.1',9000))
s.listen()
while 1:
conn,addr=s.accept()
while True:
send_content=input('服务端输入内容:').strip()
conn.send(send_content.encode('utf-8'))
if send_content.upper()=='Q':
break
msg_from_c=conn.recv(1024).decode('utf-8')
if msg_from_c.upper()=='Q':
break
print(msg_from_c)
conn.close()
#client端代码
import socket
c=socket.socket()
c.connect(('127.0.0.1',9000))
whlie True:
msg=c.recv(1024).decode('utf-8')
if msg.upper()=='Q':break
print(msg)
send_content=input('客户端输入内容:').strip()
c.send(send_content.encode('utf-8'))
f send_content.upper()=='Q':break
c.close()
UDP通信
#服务端代码
import socket
s=socket.socket(type=socket.SOCK_DGRAM)
s.bind(('127.0.0.1',9000))
msg,addr=s.recvfrom(1024)
msg=msg.decode('utf-8')
print(msg)
send_content=input('服务端输入内容:').strip().encode('utf-8')
s.sendto(send_content,addr)
#客户端代码
import socket
c=socket.socket(type=socket.SOCK_DGRAM)
server=('127.0.0.1',9000)
while True:
send_msg=input('客户端输入内容:').strip()
if send_msg.upper()=='Q':break
c.sendto(send_msg.encode('utf-8'),server)
msg=c.recv(1024).decode('utf-8')
if msg.upper()=='Q':break
print(msg)
sk.close()
开多个客户端的方法
- pycharm中的设置:Run -> Edit Configurations -> Allow parallel run
粘包现象
- 粘包就是因为tcp协议中发送的信息之间没有边界,而且涉及一大堆算法,粘包主要发生在以下两处
- 发送端:发送信息过短且发送间短
- 接收端:接受不及时,信息堆在缓存区中
- 解决粘包问题的本质就是解决边界
#Server端代码
import socket
import json
import struct
s=socket.socket()
s.bind(('127.0.0.1',9000))
s.listen()
def my_send(conn,content):
content=json.dumps(content)
send_content=content.encode('utf-8')
length=struct.pack('i',len(send_content))
conn.send(length)
conn.send(send_content)
def my_recv(conn):
length=struct.unpack('i',conn.recv(4))[0]
msg=conn.recv(length).decode('utf-8')
msg=json.loads(msg)
return msg
while 1:
conn,addr=s.accept()
while True:
send_content=input('服务端输入内容>>>').strip()
my_send(conn,send_content)
if send_content.upper()=='Q':break
msg=my_recv(conn)
if msg.upper()=='Q':break
print(msg)
conn.close()
#Server端代码
import socket
import json
import struct
c=socket.socket()
c.connect(('127.0.0.1',9000))
def my_send(c,content):
content=json.dumps(content)
send_content=content.encode('utf-8')
length=struct.pack('i',len(send_content))
c.send(length)
c.send(send_content)
def my_recv(c):
length=struct.unpack('i',c.recv(4))[0]
msg=c.recv(length).decode('utf-8')
msg = json.loads(msg)
return msg
while True:
msg=my_recv(c)
if msg.upper() == 'Q': break
print(msg)
content=input('客户端输入内容>>>').strip()
my_send(c,content)
if content.upper() == 'Q': break
c.close()
socketserver模块
并发的TCP通信
#server端代码
import socketserver
import json
import struct
def my_send(conn, content):
content = json.dumps(content)
send_content = content.encode('utf-8')
length = struct.pack('i', len(send_content))
conn.send(length)
conn.send(send_content)
def my_recv(conn):
length = struct.unpack('i', conn.recv(4))[0]
msg = conn.recv(length).decode('utf-8')
msg = json.loads(msg)
return msg
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
conn=self.request
while True:
send_content = input('服务端输入内容:')
my_send(conn, send_content)
if send_content.upper() == 'Q': break
msg = my_recv(conn)
if msg.upper() == 'Q': break
print(msg)
conn.close()
server=socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver)
server.serve_forever()
#客户端代码
import socket
import json
import struct
c=socket.socket()
c.connect(('127.0.0.1',9000))
def my_send(c,content):
content=json.dumps(content)
send_content=content.encode('utf-8')
length=struct.pack('i',len(send_content))
c.send(length)
c.send(send_content)
def my_recv(c):
length=struct.unpack('i',c.recv(4))[0]
msg=c.recv(length).decode('utf-8')
msg = json.loads(msg)
return msg
while True:
msg=my_recv(c)
if msg.upper() == 'Q': break
print(msg)
content=input('客户端输入内容>>>').strip()
my_send(c,content)
if content.upper() == 'Q': break
c.close()