python——网络编程
来源:互联网 发布:windows jenkins shell 编辑:程序博客网 时间:2024/05/21 14:00
网络通信示意图
socket编程网络步骤图
客户端
import socketclient=socket.socket()#声明socket类型,同时生成socket连接对象client.connect(("localhost",6969))#连接地址(IP地址和端口)client.send(b"hello world")#python3只能发byte字节类型data=client.recv(1024)print("recv:",data)client.close()
服务端
import socketserver=socket.socket()#声明类型,使用的是默认类型server.bind(("localhost",6969))#绑定要监听的端口server.listen()#监听print("我要开始等电话了")#conn就是客户端连过来而在服务器端为其生成的一个连接实例conn,addr=server.accept()#等电话打进来,conn就是客户端连过来而在服务器端为其生成的一个连接实例,addr链接的地址print(conn,addr) #('127.0.0.1', 3020)是地址print("电话来了")data=conn.recv(1024)print("recv:",data)conn.send(data.upper())#发送给客户端server.close()
能连续发送命令给服务端,服务端给客户端返回执行的命令结果
服务端代码
import socketimport osimport timeserver=socket.socket()server.bind(("localhost",9999))server.listen()while True: coon,addr=server.accept() print("new conn:",addr) while True: print("等待新指令") data=coon.recv(1024) if not data: print("客户端已断开") break print("执行指令:",data.decode()) cmd_res=os.popen(data.decode()).read()#接受字符串,执行结果也是字符串 print("before send",len(cmd_res)) if len(cmd_res)==0: cmd_res="cmd has no output" ''' 下面发送的两个包在一起,就有可能出现粘包的现象,因为缓冲区会把这两条语句当做一条语句发送 ''' coon.send(str(len(cmd_res.encode())).encode("utf-8"))#先发大小给客户端 #time.sleep(0.5)#这样也能解决粘包的问题,但是会产生延时,不适合实时通信的 client_ack=coon.recv(1024)#等待客户端确认,这样就不会粘包了 print("ack from client:",client_ack.decode()) coon.send(cmd_res.encode("utf-8")) print("send done")server.close()
客户端
import socketclient=socket.socket()client.connect(("localhost",9999))while True: cmd=input(">>:").strip() if len(cmd)==0: continue client.send(cmd.encode("utf-8")) cmd_res_size=client.recv(1024)#接受命令结果的长度 print("命令结果的大小:",cmd_res_size) client.send("可以开始接收了".encode("utf-8")) received_size=0 received_data=b"" while received_size<int(cmd_res_size.decode()): data=client.recv(1024) received_size+=len(data)#每次收到的可能小于1024(recv(1024)这个只是说每次最大能接受1024,而不是每次就接受1024,这个值一般最大为8792),所以必须用len判断 print(data.decode()) received_data+=data else: print("cmd res receive done...",received_size) print(received_data.decode())client.close()
单用户使用get下载文件,并能验证md5值
下载文件步骤
服务端代码
import socketimport osimport hashlibimport timeserver=socket.socket()server.bind(("localhost",9999))server.listen()while True: coon,addr=server.accept() print("new conn:",addr) while True: print("等待新指令") data=coon.recv(1024) if not data: print("客户端已断开") break cmd,filename=data.decode().split() print(filename) if os.path.isfile(filename):#判断是否为文件 f=open(filename,"rb") m=hashlib.md5() file_size=os.stat(filename).st_size#获取文件的大小 coon.send(str(file_size).encode())#发送文件长度 coon.recv(1024)#等待确认 for line in f: m.update(line) coon.send(line) print("file md5",m.hexdigest()) f.close() coon.send(m.hexdigest().encode())#给客户端发送md5值 print("send done")server.close()
客户端代码
import socketimport hashlibclient=socket.socket()client.connect(("localhost",9999))while True: cmd=input(">>:").strip() if len(cmd)==0: continue if cmd.startswith("get"): client.send(cmd.encode()) server_response=client.recv(1024) print("server response:",server_response) client.send(b"ready to recv file") file_total_size=int(server_response.decode()) received_size=0 filename=cmd.split()[1] f=open(filename+".new","wb") m=hashlib.md5() while received_size<file_total_size: ''' 通过下面的这个对size的控制可以防止位置1和位置2处发生粘包的发生,因为在接收文件最后不足1024的时候剩多少,我收多少 (粘包发生的原因就是文件收到最后不足1024的时候,可能将md5和文件不足1024的部分一起接收了,但是也有可能不发生粘包,因为每次发送接收的不一定就是1024) ''' if file_total_size-received_size>1024:#要收不止一次 size=1024 else: size=file_total_size-received_size data=client.recv(size)#位置1 received_size+=len(data) m.update(data) f.write(data) print(file_total_size,received_size) else: new_file_md5=m.hexdigest() print("file recv done") f.close() server_file_md5=client.recv(1024)#位置2 print("server file md5:",server_file_md5) print("client file md5:",new_file_md5)client.close()
* 支持多用户同时上传下载(并发)——socketServer,简例*
创建一个sockerServer的步骤
服务端
import socketserverclass MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: try: self.data=self.request.recv(1024).strip() print("{} wrote".format(self.client_address[0])) print(self.data) # if not self.data:#客户端断了 # print(self.client_address,"断开了") # break self.request.send(self.data.upper()) except ConnectionResetError as e: print("err",e) breakif __name__== "__main__": HOST,PORT="localhost",9999 #创建服务端,绑定主机端口9999 server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)#多线程并发 #server=socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler)#多进程并发,在windows上不好使,在Linux上可以,因为windows上的进程不能通过fork实现 server.serve_forever()
客户端
import socketclient=socket.socket()#声明socket类型,同时生成socket连接对象client.connect(("localhost",9999))#连接地址(IP地址和端口)while True: msg=input(">>:").strip() client.send(msg.encode("utf-8"))#python3只能发byte字节类型 data=client.recv(1024) print("recv:",data.decode())client.close()
简易版的ftp并发上传
客户端代码
import socketimport osimport jsonclient=socket.socket()client.connect(("localhost",9999))class FtpClient(object): def __init__(self): self.client=socket.socket() def help(self): msg=''' ls pwd cd ../.. get filename put filename ''' print(msg) def connect(self,ip,port): self.client.connect((ip,port)) def interactive(self): #self.authenticate() while True: cmd=input(">>").strip() if len(cmd)==0: continue cmd_str=cmd.split()[0] if hasattr(self,"cmd_%s"%cmd_str):#反射 func=getattr(self,"cmd_%s"%cmd_str) func(cmd) else: self.help() def cmd_put(self,*args): cmd_split=args[0].split() if len(cmd_split)>1: filename=cmd_split[1] if os.path.isfile(filename): filesize=os.stat(filename).st_size msg_dic={ "action":"put", "filename":filename, "size":filesize, "overridden":True } self.client.send(json.dumps(msg_dic).encode("utf-8")) print("send",json.dumps(msg_dic).encode("utf-8")) #防止粘包,等服务器确认 server_response=self.client.recv(1024) f=open(filename,"rb") for line in f: self.client.send(line) else: print("file upload success...") f.close() else: print(filename,"is not exist") def cmd_get(self): passftp=FtpClient()ftp.connect("localhost",9999)ftp.interactive()
服务端代码
import socketserverimport jsonimport osclass MyTCPHandler(socketserver.BaseRequestHandler):#括号里面的是固定的 def put(self,*args): '''接收客户端文件''' cmd_dic=args[0] filename=cmd_dic["filename"] filesize=cmd_dic["size"] if os.path.isfile(filename): f=open(filename+".new","wb") else: f=open(filename,"wb") self.request.send(b"200 ok") received_size=0 while received_size<filesize: data=self.request.recv(1024) f.write(data) received_size+=len(data) else: print("file [%s] has uploaded..."%filename) def handle(self):#这里面的才是跟客户端交互的 while True: try: self.data=self.request.recv(1024).strip() print("{} wrote".format(self.client_address[0])) print(self.data) cmd_dic=json.loads(self.data.decode()) action=cmd_dic["action"] if hasattr(self,action):#判断是否有action所对应的字符串的函数 func=getattr(self,action)#获取action对应的函数 func(cmd_dic)#执行其对应的函数 except ConnectionResetError as e:#捕获异常的 print("err",e) break'''下面是固定的写法'''if __name__== "__main__": HOST,PORT="localhost",9999 #创建服务端,绑定主机端口9999 server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) server.serve_forever()
阅读全文
0 0
- python——网络编程
- python——网络编程
- Python——网络编程
- Python笔记—网络编程
- PYthon -网络编程—TCP编程
- Python基础教程——14 网络编程
- python网络编程——TCP
- Python基础——网络编程
- Python网络编程——学习笔记
- Python学习笔记(十)——Python 网络编程
- Python高级编程——14.网络编程
- python核心编程(十三&十四)— 网络编程、网络客户端编程
- python网络编程——读取网站根目录
- python学习第十四章——网络编程
- Python 标准库 —— socket(网络编程)
- python 网络编程——urllib,urllib2简单运用
- python网络编程——IO多路复用之epoll
- python网络编程——IO多路复用之epoll
- Python MySQL使用与实例
- Who's in the Middle
- NYOJ_1140 鸡蛋栈
- 解决Ubuntu:e1000e无法驱动无法上网问题
- mysql的监控和排错
- python——网络编程
- 大佬图论注解
- mybatis
- JDK配置环境变量
- Mac破解版软件大全
- Leetcode算法学习日志-576 Out of Boundary Paths
- Swift3.0基本语法01
- Swift3.0基本语法02
- 什么是敏捷过程和XP?