day 08 初识网络编程
刚刚结束面向对象,换了新老师,讲网络编程。收获的话,从实际意义明白了网络连接,收发啊的细节。聊天:
import socket sock = socket.socket() sock.connect(('127.0.0.1',8800)) while 1: first = sock.recv(1024) print(first.decode('utf-8')) cont = input('输入:') sock.sendall(cont.encode('utf-8')) if cont == 'q': break message = sock.recv(1024) if message.decode('utf-8') == 'q': print('对方断开') break print('收到:',message.decode('utf-8')) sock.close()
import socket # # sock = socket.socket() # sock.bind(('127.0.0.1',8800)) # sock.listen(5) # conn , addr = sock.accept() # print('连接已建立') # conn.sendall('欢迎'.encode('utf-8')) # data = conn.recv(1024) # print('收到:',data.decode('utf-8')) # conn.sendall('开始聊天吧'.encode('utf-8')) # print('聊天开始'.center(20,'-')) # while 1: # content = input('输入:') # conn.sendall(content.encode('utf-8')) # message = conn.recv(1024) # print('收到:',message.decode('utf-8')) ''' 可退出版 ''' import socket sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server is working...') conn, addr = sock.accept() print('连接已建立') while 1: try: conn.sendall('欢迎'.encode('utf-8')) message = conn.recv(1024) if message.decode('utf-8') == 'q': print('对方断开连接') break print('收到了:', message.decode('utf-8')) response = input('输入:').encode('utf-8') conn.sendall(response) if response.decode('utf-8') == 'q': break except Exception as e: break conn.close()
重点的话,在于了解收发的对应吧,还有一些异常的处理
ssh:
import socket import struct sock = socket.socket() sock.connect(('127.0.0.1',8800)) first = sock.recv(1024) print(first.decode('utf-8')) while 1: cmd = input('>>>') sock.sendall(cmd.encode('utf-8')) if cmd == 'q': break if len(cmd) == 0: continue header = sock.recv(4) data_len = struct.unpack('i',header)[0] if not data_len: print('输入命令有误,请重输!') continue print('数据长度:',data_len) recv_data = b'' has_recv_len = 0 while has_recv_len < data_len: message = sock.recv(1024) recv_data += message has_recv_len += len(message) print('收到:',recv_data.decode('gbk')) sock.close()
import struct import socket import subprocess sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server is working...') conn, addr = sock.accept() print('连接已建立') conn.sendall('欢迎'.center(10,'-').encode('utf-8')) while 1: try: message = conn.recv(1024) s = message.decode('utf-8') if s == 'q': print('对方断开连接') break print(s) a = subprocess.Popen(s, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) reaction = a.stdout.read() print('len',len(reaction)) reaction_len = struct.pack('i',len(reaction)) conn.sendall(reaction_len) conn.sendall(reaction) except Exception as e: break conn.close()
重点是了解黏包,并解决,这里用到两个新东西,struct和subprocess
再到ftp:0.5版本,参照之前的思路,实现了上传这一个功能。
import socket import os import json import struct sock = socket.socket() sock.connect(('127.0.0.1',8800)) print('已连接ftp服务器...') cmd = input('输入操作及文件路径') operation,file_name = cmd.split('|') file_size = os.path.getsize(file_name) head = {'操作':operation, '文件名称':file_name, '文件大小':file_size} head_json = json.dumps(head) head_len = struct.pack('i',len(head_json)) sock.sendall(head_len) sock.sendall(head_json.encode('utf-8')) with open(file_name,'rb') as f: for line in f: sock.sendall(line)
import socket import json import struct sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server is working...') conn,addr = sock.accept() print('有客户端接入') while 1: try: head_len = struct.unpack('i',conn.recv(4))[0] print(head_len) head_json = conn.recv(head_len) head = json.loads(head_json.decode('utf-8')) print(head) file_size = head['文件大小'] file_name = head['文件名称'] print(file_size) recv_data = b'' with open('putdir/'+ file_name,'wb') as f: has_recv_len = 0 while has_recv_len < file_size: data = conn.recv(1024) recv_data += data has_recv_len += len(data) f.write(data) except Exception as e: break
然后是1.0版本,用了面向对象,有用户登录,上传下载,而且比较满意的是 异常的处理和条件的判断
import socket import json import struct import sys import os base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_path) from core import auth from tool import mkdir class Ftp_client: ret = auth.login() def __init__(self,ip_port): ''' 负责初始化操作, :param ip_port: ''' self.sock = socket.socket() self.address = ip_port #登录 if Ftp_client.ret: folder_path = os.path.join(base_path,Ftp_client.ret['name']) mkdir.mkdir(folder_path) #登录成功创建一个属于该用户的文件夹 try: self.client_connect() except: self.client_close() raise def client_connect(self): self.sock.connect(self.address) def client_close(self): self.sock.close() def run(self): ''' 登陆成功后,执行客户端操作 :return: ''' while 1: cmd = input('请输入:(格式:操作|文件)\n').strip() if not cmd: continue try: operation,filename = cmd.split('|') except ValueError: print('未按照格式输入') continue if hasattr(self, operation): #print(operation) self.sock.sendall(cmd.encode('utf-8')) getattr(self, operation)(filename) else: print('没有此操作') def put(self,file): ''' 上传文件 :param file: :return: ''' file_path = os.path.join(base_path,'db',file) if not os.path.isfile(file_path): print('文件:%s 不存在' % file_path) return else: filesize = os.path.getsize(file_path) head = {'文件名称': file, '文件大小': filesize} head_json = json.dumps(head) head_len = struct.pack('i', len(head_json)) self.sock.sendall(head_len) self.sock.sendall(head_json.encode('utf-8')) with open(file_path, 'rb') as f: for line in f: self.sock.sendall(line) print('上传完成') def get(self,file): ''' 下载文件 :param file: :return: ''' head_len = struct.unpack('i', self.sock.recv(4))[0] #print(head_len) head_json = self.sock.recv(head_len) head = json.loads(head_json.decode('utf-8')) #print(head) file_size = head['文件大小'] file_name = head['文件名称'] #print(file_size) if head['文件存在状态']:# print('开始下载') recv_data = b'' with open(os.path.join(base_path,Ftp_client.ret['name'], file_name), 'wb') as f: has_recv_len = 0 while has_recv_len < file_size: data = self.sock.recv(1024) recv_data += data has_recv_len += len(data) f.write(data) print('下载完成') else: print('您要下载的文件不存在!') a = Ftp_client(('127.0.0.1',8800)) a.run()
import socket import json import os,sys import struct import socketserver import os import sys base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_path) class Ftp_Server: def __init__(self,ip_port): self.sock = socket.socket() self.address = ip_port try: self.server_bind() self.server_listen() except: self.server_close() raise def server_bind(self): self.sock.bind(self.address) def server_listen(self): self.sock.listen(5) def server_accept(self): return self.sock.accept() def server_close(self): self.sock.close() def run(self): while 1: print('server is working...') self.conn,self.addr = self.server_accept() print('from client',self.addr) while 1: try: cmd = self.conn.recv(1024).decode() print(cmd) operation,filename = cmd.split('|') getattr(self,operation)(filename) except Exception: break def put(self,file): ''' 对应用户的上传 :param file: :return: ''' head_len = struct.unpack('i', self.conn.recv(4))[0] print(head_len) head_json = self.conn.recv(head_len) head = json.loads(head_json.decode('utf-8')) print(head) file_size = head['文件大小'] file_name = head['文件名称'] print(file_size) recv_data = b'' file_path = os.path.join(base_path,'cloud',file_name) print(file_path) with open(file_path, 'wb') as f: has_recv_len = 0 while has_recv_len < file_size: data = self.conn.recv(1024) recv_data += data has_recv_len += len(data) f.write(data) def get(self,file): ''' 对应用户的下载 :param file: :return: ''' status = True #文件是否存在的状态标志 file_path = os.path.join(base_path,'home',file)#拼出文件完整目录 if not os.path.isfile(file_path): status = False filesize = 0 else: filesize = os.path.getsize(file_path) print(status,111) head = {'文件存在状态':status, '文件名称': file, '文件大小': filesize} head_json = json.dumps(head) head_len = struct.pack('i', len(head_json)) self.conn.sendall(head_len) self.conn.sendall(head_json.encode('utf-8')) if status: with open(file_path, 'rb') as f: for line in f: self.conn.sendall(line) else: return a = Ftp_Server(('127.0.0.1',8800)) a.run()
缺点是没能并发,多个用户,主要是socketserver 没看懂。
网络编程开始,代码的量就一下上来了。一是有两个文件client和server,二是收发的信息又是会重复
总体我还是很满意这次的作业,从一开始毫无思路,到面向过程写上传,再到看懂面向对象,再到自己调试,程序越来越健壮。

浙公网安备 33010602011771号