文章目录
第十二章:网络编程
一、基本概念
"""
一、客户端和服务端架构
C/S架构
client--------互联网--------server
B/S
browser--------互联网--------server
服务端:
1、一直对外提供服务
2、服务端的必须绑定一个固定的地址
3、并发能力
二、网络通信
互联网存在的意义?
互联网存在的意义让通信变得方便 =》通信
什么是互联网?
网络=底层物理连接介质+互联网通信协议
ip+mac=》标识全世界范围内独一无二的一台计算机
ip+mac+port=》标识全世界范围内独一无二的一个基于网络通信的应用软件
因为ARP协议的存在,可以将ip解析成mac,所以:
ip+port=》标识全世界范围内独一无二的一个基于网络通信的应用软件
三、OSI七层协议
七层协议:
1.应用层:OSI 的应用层协议包括文件的传输、访问及管理协议(FTAM) ,以及文件虚拟终端协议(VIP)和公用管理系统信息(CMIP)等
2.表示层:供多种功能用于应用层数据编码和转化,以确保以一个系统应用层发送的信息 可以被另一个系统应用层识别
3.会话层:建立、管理和终止表示层与实体之间的通信会话
4.传输层:向高层提供可靠的端到端的网络数据流服务
5.网络层:负责在源和终点之间建立连接
6.数据链接层:通过物理网络链路提供数据传输。不同的数据链路层定义了不同的网络和协 议特征,其中包括物理编址、网络拓扑结构、错误校验、数据帧序列以及流控
7.物理层:物理层负责最后将信息编码成电流脉冲或其它信号用于网上传输
四、五层协议
应用层
传输层
网络层
数据链路层
物理层
五、协议:规定数据的组织规格
格式:头部+数据部分
封包裹的过程:数据外加头
拆包裹的过程:拆掉头获取数据
计算机1: 计算机2:
应用层 应用层
传输层 传输层
网络层 网络层
数据链路层 数据链路层
物理层 <===========交互机===========> 物理层
0101010101010
(源mac地址,目标mac地址)(源ip地址,目标ip地址)数据
"""
二、socket是什么?
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
三、基于TCP的套接字编程
客户端
import socket
# 获取tcp/ip套接字
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
phone.connect(("127.0.0.1",8080)) # ip和port
phone.send("hello".encode('utf-8'))
data=phone.recv(1024) # 最大接收1024个字节
print(data)
phone.close()
服务端
import socket
# 1、买电话
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# print(phone)
# 2、插电话卡
phone.bind(("127.0.0.1",8080))
# 3、开机
phone.listen(5)
print("starting:%s:%s" %("127.0.0.1",8080))
# 4、等电话连接
conn,client_addr=phone.accept()
# print(conn,client_addr)
print(client_addr)
# 5、收/发消息
data=conn.recv(1024) # 最大接收1024个字节
print(data)
conn.send(data.upper())
# 6、挂电话
conn.close()
# 7、关机
phone.close()
四、加上循环的套接字
客户端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
phone.connect(("127.0.0.1",8081))
while True:
msg=input('>>: ').strip() # msg=''
if len(msg) == 0:continue
phone.send(msg.encode('utf-8'))
# print('has send=====>')
data=phone.recv(1024)
# print('has recv=====>')
print(data)
phone.close()
服务端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(("127.0.0.1",8081))
phone.listen(5)
print("starting:%s:%s" %("127.0.0.1",8081))
# 链接循环
while True:
conn,client_addr=phone.accept()
print(client_addr)
# 通信循环
while True:
try: # 针对windows系统
data=conn.recv(1024) # 最大接收1024个字节
if len(data) == 0:break # 针对linux系统
print(data)
conn.send(data.upper())
except Exception:
break
conn.close()
phone.close()
五、远程执行命令的程序
客户端
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
phone.connect(("127.0.0.1",8082))
while True:
cmd=input('>>: ').strip() # msg=''
if len(cmd) == 0:continue
phone.send(cmd.encode('utf-8'))
data=phone.recv(1024)
print(data.decode('gbk'))
phone.close()
服务端
import socket
import subprocess
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
phone.bind(("127.0.0.1",8082))
phone.listen(5)
# 链接循环
while True:
conn,client_addr=phone.accept()
print(client_addr)
# 通信循环
while True:
try: # 针对windows系统
cmd=conn.recv(1024) # 最大接收1024个字节
if len(cmd) == 0:break # 针对linux系统
obj = subprocess.Popen(
cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
conn.send(obj.stdout.read())
conn.send(obj.stderr.read())
except Exception:
break
conn.close()
phone.close()
struct模块的应用
import struct
res = struct.pack('i',10241111)
print(res, len(res))
recv_header = struct.unpack('i', res)
print(recv_header[0])
# b'WD\x9c\x00' 4
# 10241111
服务端
import socket
import subprocess
import struct
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)
# 链接循环
while True:
conn,addr=server.accept()
print(addr)
# 通信循环
while True:
try:
cmd=conn.recv(1024)
if len(cmd) == 0:break # 针对linux
obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_res=obj.stdout.read()
stderr_res=obj.stderr.read()
total_size=len(stdout_res) + len(stderr_res)
print(total_size)
# 1、先发送数据的总大小
conn.send(struct.pack('i',total_size))
# 2、再发送真实的数据
conn.send(stdout_res)
conn.send(stderr_res)
except Exception: # 针对windows
break
conn.close()
server.close()
客户端
import socket
import struct
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
# 1、先拿到数据的总大小
header_bytes=client.recv(4)
header=struct.unpack('i',header_bytes)
total_size=header[0]
# 2、再接收数据
recv_size=0
res=b''
while recv_size < total_size:
data=client.recv(1024)
recv_size+=len(data)
res+=data
print(res.decode('gbk'))
六、解决粘包问题
struct模块的应用
import struct
import json
header_dic={
'filenme':"a.txt",
'md5':"sdfasfdasfdasfd123123213",
"total_size":999999912343123442802
}
header_json=json.dumps(header_dic)
header_json_bytes=header_json.encode('utf-8')
# print(header_json_bytes)
# print(len(header_json_bytes))
服务端
import socket
import subprocess
import struct
import json
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)
# 链接循环
while True:
conn,addr=server.accept()
print(addr)
# 通信循环
while True:
try:
cmd=conn.recv(1024)
if len(cmd) == 0:break # 针对linux
obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_res=obj.stdout.read()
stderr_res=obj.stderr.read()
total_size=len(stdout_res) + len(stderr_res)
print(total_size)
header_dic = {
'filenme': "a.txt",
'md5': "sdfasfdasfdasfd123123213",
"total_size": total_size
}
header_json = json.dumps(header_dic)
header_json_bytes = header_json.encode('utf-8')
# 1、先发送报头的长度
conn.send(struct.pack('i',len(header_json_bytes)))
# 2、再发送报头
conn.send(header_json_bytes)
# 3、然后发送真实的数据
conn.send(stdout_res)
conn.send(stderr_res)
except Exception: # 针对windows
break
conn.close()
server.close()
客户端
import socket
import struct
import json
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
# 1、先拿到报头的长度
header_json_bytes_size=struct.unpack('i',client.recv(4))[0]
# 2、再收报头
header_json_bytes=client.recv(header_json_bytes_size)
header_json=header_json_bytes.decode('utf-8')
header_dic=json.loads(header_json)
print(header_dic)
# 3、最后接收数据
total_size=header_dic['total_size']
recv_size=0
res=b''
while recv_size < total_size:
data=client.recv(1024)
recv_size+=len(data)
res+=data
print(res.decode('gbk'))
七、基于udp协议的套接字通信
服务端
# import socket
from socket import *
import time
server=socket(AF_INET,SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
data,client_addr=server.recvfrom(1024)
time.sleep(10)
server.sendto(data.upper(),client_addr)
客户端
# import socket
from socket import *
client = socket(AF_INET, SOCK_DGRAM)
while True:
msg=input('>>>: ').strip()
client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'))
八、socket server模块
(一) TCP协议
服务端
import socketserver
class MyrequestHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request # conn对象
print(self.client_address)
while True:
try:
data=self.request.recv(1024)
if len(data) == 0:break
self.request.send(data.upper())
except Exception:
break
self.request.close()
if __name__ == '__main__':
s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyrequestHandler)
s.serve_forever()
客户端
import socket
import struct
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp
client.connect(('127.0.0.1',8080))
while True:
cmd=input(">>>: ").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
(二) UDP协议
服务端
import socketserver
import time
class MyrequestHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request # conn对象
data=self.request[0]
self.request[1].sendto(data.upper(),self.client_address)
time.sleep(10)
if __name__ == '__main__':
s=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyrequestHandler)
s.serve_forever()
客户端
# import socket
from socket import *
client = socket(AF_INET, SOCK_DGRAM)
while True:
msg=input('>>>: ').strip()
client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'))
作者:吴常文
出处:https://blog.csdn.net/qq_41405475
本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。