python网络编程和编码
1 网络通信要素
OSI模型定义不同计算机互联网的标准,设计和描述计算机网络通信的基本框架。
1)IP地址:用来表示网络上一台独立的主机;IP地址=网络地址+主机地址;特殊IP地址:127.0.0.1(本地回环地址,保留地址,点份十进制)。
2)端口号:要将数据发送到对方的指定的应用程序上,为了表示这些应用程序,所有这些网络应用程序都用数字进行标识,为了方便称呼这些数字,则将这些数字称为端口。
3)传送协议:通讯的规则,例如:TCP,UDP协议(好比两个人用统一中国语言进行交流)。
2 网络通讯步骤
确定对方IP地址->确定应用程序端口->确定通讯协议
网络通讯的过程其实就是一个(源端)不断的封装数据包(目的端)不断拆数据包的过程。
3 通信的方法
server下的方法
sk.accept()接收的是客户端的sk相关信息,返回信息类型为元组。
bind()
listen()
send()
sendall()
recv()
close(),关通道与关服务器是不同的。关通道不影响其它通道。
1 import socket 2 3 # family=AF_INET是指定使用何种的地址类型,ADDRESS FAMILY是地址族,INET:internetwork。 4 # type确定设置通信的协议类型,SOCK_SREAM。 5 sk = socket.socket() 6 print(sk) 7 # 绑定IP地址 8 address = ('127.0.0.1', 8000) 9 sk.bind(address) 10 sk.listen(3) # 确定连接的最大数量 11 print("waitting...") 12 # conn就是通道,所有的数据连接都是通过conn连接。 13 conn, addr = sk.accept() # 创建连接 14 inp = input("请输入") 15 conn.send(bytes(inp, 'utf-8')) # 传送的类型是bytes类型
listen()
recv()
send()
close()
1 import socket 2 3 # 不需要绑定,直接绑定 4 sk = socket.socket() 5 address = ('127.0.0.1', 8000) 6 sk.connect(address) 7 8 data = sk.recv(1024) # 一次最大接收多少 9 print(str(data, 'utf-8')) # 如果接受是汉字,需要进行编码 10 11 # 只关闭自己的通道,其它的对象没有关系 12 sk.close()
4 实际应用聊天
1 import socket 2 3 sk = socket.socket() 4 print(sk) 5 address = ('127.0.0.1', 8000) 6 sk.bind(address) 7 sk.listen(3) # 最大排队数,排队数量为3个。 8 print("waitting...") 9 # conn, addr = sk.accept() # 此处也可增加一个while循环。 10 11 12 while 1: 13 conn, addr = sk.accept() 14 print(addr) 15 while True: 16 try: 17 data = conn.recv(1024) # 此处异常关闭客户端会出现异常 18 except Exception as e: 19 print(e) 20 break # 跳出里层的循环 21 if not data: 22 break 23 inp = input("请输入") 24 conn.send(bytes(inp, 'utf-8')) # 传送的类型是bytes类型 25 26 conn.close()
1 import socket 2 3 # 不需要绑定,直接绑定 4 sk = socket.socket() 5 address = ('127.0.0.1', 8000) 6 sk.connect(address) 7 8 while True: 9 inp = input('>>>') 10 if inp == "exit": 11 break 12 sk.send(bytes(inp, 'utf-8')) # 不能发空 13 14 data = sk.recv(1024) # 一次最大接收多少 15 print(str(data, 'utf-8')) # 如果接受是汉字,需要进行编码 16 sk.close()
5 远程执行命令
编码:从明文到编码文本的转换过程叫做编码。
解码:从编码文本到明文的转换过程叫做解码。
Python2的string编码
在Python2中,有两种字符串类型:str类型和unicode类型;注意,这仅仅是两个名字,python定义的两个名字,关键是这两种数据类型在程序运行时存在内存地址的是什么?内置函数repr可以帮我们在这里显示存储内容。原来,str和unicode分别存的是字节数据和unicode数据。
Python3的string编码
Python3也有两种数据类型:str和bytes; str类型存unicode数据,bytse类型存bytes数据,与py2比只是换了一下名字而已
文件从磁盘到内存的编码
例如在文本编辑器word上编辑文字的时候,在保存数据之前通过unicode的形式存在内存中,当保存到磁盘上时通过某种编码方式编码成bytes字节串,例如utf-8等,
1 s = 'hello 袁浩' # uicode万国码,在哪个国家都是相同的 2 print(type(s)) # <class 'str'> 3 4 # 由str到bytes:编码 5 b1 = bytes(s, 'utf-8') 6 print("b1", b1) # b'hello \xe8\xa2\x81\xe6\xb5\xa9' UTF-8规则下的bytes类型 7 b2 = s.encode('utf-8') # encode()是编码,有看到的数字转化为utf-8的数字 8 print("b2", b2) 9 b3 = s.encode('gbk') 10 print("b3", b3) 11 12 13 # 由bytes到str:解码 14 s1 = str(b2, 'utf-8') # 解码的一种方式 15 print('s1', s1) 16 s2 = b2.decode('utf-8') 17 print('s2', s2) 18 s3 = b3.decode('gbk') 19 print('s3', s3) 20 21 22 # cmd_result = obj.stdout.read() # 数据类型为gbk,Windows下自动转成gbk
1 import socket 2 import subprocess 3 4 sk = socket.socket() 5 print(sk) 6 address = ('127.0.0.1', 8000) 7 sk.bind(address) 8 sk.listen(3) # 最大排队数,排队数量为3个。 9 print("waitting...") 10 11 while 1: 12 conn, addr = sk.accept() 13 print(addr) 14 while True: 15 try: 16 data = conn.recv(1024) # 此处异常关闭客户端会出现异常 17 except Exception as e: 18 break # 跳出里层的循环 19 if not data: 20 break 21 print('-------', str(data, 'utf-8')) 22 obj = subprocess.Popen(str(data, 'utf-8'), shell=True, stdout=subprocess.PIPE) # PIPE是个类 23 cmd_result = obj.stdout.read() 24 result_len = bytes(str(len(cmd_result)), 'utf-8') # int和bytes不能直接转,需要有通过str来转 25 conn.sendall(result_len) # 粘包现象,连续send() 26 conn.recv(1024) 27 conn.sendall(cmd_result) # 传送的类型是bytes类型 28 29 sk.close()
1 import socket 2 3 # 不需要绑定,直接绑定 4 sk = socket.socket() 5 address = ('127.0.0.1', 8000) 6 sk.connect(address) 7 8 while True: 9 inp = input('>>>') 10 if inp == "exit": 11 break 12 sk.send(bytes(inp, 'utf-8')) # 不能发空 13 result_len = int(str(sk.recv(1024), 'utf-8')) 14 sk.sendall('ok') # 解决粘包现象 15 print(result_len) 16 data = bytes() 17 while len(data) != result_len: 18 recv = sk.recv(1024) # 一次最大接收多少 19 data += recv 20 print(str(data, 'gbk')) # 如果接受是汉字,需要进行编码 21 22 sk.close()
6 文件上传
1 import socket 2 import subprocess 3 import os 4 5 sk = socket.socket() 6 print(sk) 7 address = ('127.0.0.1', 8000) 8 sk.bind(address) 9 sk.listen(3) # 最大排队数,排队数量为3个。 10 print("waitting...") 11 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 12 13 while True: 14 conn, addr = sk.accept() 15 while True: 16 data = conn.recv(1024) 17 cmd, filename, filesize = str(data, 'utf-8').split('|') 18 path = os.path.join(BASE_DIR, 'yuan', filename) 19 filesize = int(filesize) 20 21 f = open(path, 'ab') 22 has_receive = 0 23 while has_receive != filesize: 24 data = conn.recv(1024) 25 f.write(data) 26 has_receive += len(data) 27 f.close() 28 sk.close()
1 import socket 2 import os 3 4 sk = socket.socket() 5 print(sk) 6 7 addresss = ('127.0.0.1', 8000) 8 sk.connect(addresss) 9 10 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 11 12 inp = input('>>>').strip() # post|产品目录1.xlsx 13 14 cmd, path = inp.split('|') 15 path = os.path.join(BASE_DIR, path) # 文件的绝对路径 16 17 filename = os.path.basename(path) # 取名字 18 filesize = os.stat(path).st_size 19 20 file_info = 'post|%s|%s' % (filename, filesize) 21 sk.sendall(bytes(file_info, 'utf-8')) 22 23 f = open(path, 'rb') 24 has_sent = 0 25 while has_sent != filesize: 26 data = f.read(1024) 27 sk.sendall(data) 28 has_sent += len(data) # int数据类型 29 f.close() 30 print('上传成功') 31 32 sk.close()
7 socketserver模块
1 import socketserver 2 3 4 class MyServer(socketserver.BaseRequestHandler): # 继承里面的类是固定的 5 6 def handle(self): 7 print('服务端启动...') 8 while True: 9 conn = self.request 10 print('来自服务端的地址:', self.client_address) 11 while True: 12 client_data = conn.recv(1024) 13 print("收到客户端信息:", str(client_data, 'utf-8')) 14 # print('服务端准备输入发送数据!') 15 server_response = input("服务端准输入:") 16 conn.sendall(bytes(server_response, 'utf-8')) # 原路返回 17 conn.close() 18 19 20 if __name__ == "__main__": 21 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8091), MyServer) 22 23 server.serve_forever() # 启动
1 import socket 2 3 ip_port = ('127.0.0.1', 8091) 4 sk = socket.socket() 5 sk.connect(ip_port) 6 print('客户端启动:') 7 8 while True: 9 inp = input("客户端输入:") 10 if inp == 'exit': 11 break 12 sk.sendall(bytes(inp, 'utf-8')) 13 data = sk.recv(1024) 14 print('服务器返回:', str(data, 'utf-8')) 15 16 sk.close()
8 参考来源
https://www.cnblogs.com/aylin/p/5572104.html
https://www.cnblogs.com/wangshuyang/p/7049942.html
浙公网安备 33010602011771号