一、socketserver实现多并发

socket只能实现单进程通讯,要实现多进程同时和服务端通讯就要使用socketserver。

代码如下:

 import socket
client = socket.socket()
client.connect(("localhost",9000))
while True:
choice = input(">>>:")
if len(choice) == 0:continue
client.send(choice.encode())
recv = client.recv(1024)
print("recved:",recv.decode())
 #!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Liumj
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
self.data = self.request.recv(1024).strip()
print(self.client_address[0])
print(self.data)
self.request.sendall(self.data.upper())
if __name__ =="__main__":
HOST,PORT = "localhost",9000
server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
server.serve_forever()

二、FTP程序开发

1.服务端代码

 import socketserver
import configparser
from conf import settings
import os
import hashlib
import time
t = time.strftime("%H_%M_%S") STATUS_CODE = {
250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
251 : "Invalid cmd ",
252 : "Invalid auth data",
253 : "Wrong username or password",
254 : "Passed authentication",
255 : "Filename doesn't provided",
256 : "File doesn't exist on server",
257 : "ready to send file",
258 : "md5 verification",
}
import json
class FTPHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
self.data = self.request.recv(1024).strip()
print(self.client_address[0])
print(self.data)
if not self.data:
print("client closed...")
break
data = json.loads(self.data.decode())
if data.get('action') is not None:
print("---->",hasattr(self,"_auth"))
if hasattr(self,"_%s"%data.get('action')):
func = getattr(self,"_%s"% data.get('action'))
func(data)
else:
print("invalid cmd")
self.send_response(251)
else:
print("invalid cmd format")
self.send_response(250) def send_response(self,status_code,data=None):
'''向客户端返回数据'''
response = {'status_code':status_code,'status_msg':STATUS_CODE[status_code]}
if data:
response.update( data )
self.request.send(json.dumps(response).encode()) def _auth(self,*args,**kwargs):
data = args[0]
if data.get("username") is None or data.get("password") is None:
self.send_response(252) user =self.authenticate(data.get("username"),data.get("password"))
if user is None:
self.send_response(253)
else:
print("passed authentication",user)
self.user = user
self.send_response(254)
def authenticate(self,username,password):
'''验证用户合法性,合法就返回用户数据''' config = configparser.ConfigParser()
config.read(settings.ACCOUNT_FILE)
if username in config.sections():
_password = config[username]["Password"]
if _password == password:
print("pass auth..",username)
config[username]["Username"] = username
return config[username] def _put(self,*args,**kwargs):
"client send file to server"
data = args[0]
# if data.get('filename') is None:
# self.send_response(255)
user_home_dir = "%s/%s" % (settings.USER_HOME, self.user["Username"])
file_abs_path = "%s/%s" % (user_home_dir, data.get('filename'))
print("file abs path", file_abs_path)
print("server.....")
self.send_response(257)
received_size = 0
total_size = int(self.request.recv(1024))
file_obj = open(file_abs_path+t, "wb")
#print("zhaodao.....")
while received_size < total_size:
data = self.request.recv(4096)
received_size +=len(data)
file_obj.write(data)
else:
print("---recv done...")
file_obj.close() def _get(self,*args,**kwargs):
data = args[0]
if data.get('filename') is None:
self.send_response(255)
user_home_dir = "%s/%s" %(settings.USER_HOME,self.user["Username"])
file_abs_path = "%s/%s" %(user_home_dir,data.get('filename'))
print("file abs path",file_abs_path) if os.path.isfile(file_abs_path):
file_obj = open(file_abs_path,"rb")
file_size = os.path.getsize(file_abs_path)
self.send_response(257,data={'file_size':file_size})
self.request.recv(1) #等待客户端确认 if data.get('md5'):
md5_obj = hashlib.md5()
for line in file_obj:
self.request.send(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258,{'md5':md5_val})
print("send file done....")
else:
for line in file_obj:
self.request.send(line)
else:
file_obj.close()
print("send file done....")
else:
self.send_response(256) def _ls(self,*args,**kwargs):
pass def _cd(self, *args, **kwargs):
pass if __name__ == "__main__":
HOST, PORT = "localhost", 9000

ftp_server

2.客户端代码

 import socket
import os ,json
import optparse
import getpass
import hashlib
import sys STATUS_CODE = {
250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
251 : "Invalid cmd ",
252 : "Invalid auth data",
253 : "Wrong username or password",
254 : "Passed authentication",
255 : "Filename doesn't provided",
} class FTPClient(object):
def __init__(self):
parser = optparse.OptionParser()
parser.add_option("-s","--server", dest="server", help="ftp server ip_addr")
parser.add_option("-P","--port",type="int", dest="port", help="ftp server port")
parser.add_option("-u","--username", dest="username", help="username")
parser.add_option("-p","--password", dest="password", help="password")
self.options , self.args = parser.parse_args()
self.verify_args(self.options,self.args)
self.make_connection() def make_connection(self):
self.sock = socket.socket()
self.sock.connect((self.options.server,self.options.port)) def verify_args(self, options,args):
'''校验参数合法型'''
if options.username is not None and options.password is not None:
pass
elif options.username is None and options.password is None:
pass
else:
#options.username is None or options.password is None:
exit("Err: username and password must be provided together..") if options.server and options.port:
#print(options)
if options.port >0 and options.port <65535:
return True
else:
exit("Err:host port must in 0-65535") def authenticate(self):
'''用户验证'''
if self.options.username:
print(self.options.username,self.options.password)
return self.get_auth_result(self.options.username, self.options.password)
else:
retry_count = 0
while retry_count <3:
username = input("username:").strip()
password = input("password:").strip()
return self.get_auth_result(username,password) def get_auth_result(self,user,password):
data = {'action':'auth',
'username':user,
'password':password} self.sock.send(json.dumps(data).encode())
response = self.get_response()
if response.get('status_code') == 254:
print("Passed authentication!")
self.user = user
return True
else:
print(response.get("status_msg")) def get_response(self):
'''得到服务器端回复结果'''
data = self.sock.recv(1024)
print("server res", data)
data = json.loads(data.decode())
return data def interactive(self):
if self.authenticate():
print("---start interactive iwth u...")
while True:
choice = input("[%s]:"%self.user).strip()
if len(choice) == 0:continue
cmd_list = choice.split()
if hasattr(self,"_%s"%cmd_list[0]):
func = getattr(self,"_%s"%cmd_list[0])
func(cmd_list)
else:
print("Invalid cmd.") def __md5_required(self,cmd_list):
'''检测命令是否需要进行MD5验证'''
if '--md5' in cmd_list:
return True
def show_progress(self,total):
received_size = 0
current_percent = 0
while received_size < total:
if int((received_size / total) * 100 ) > current_percent :
print("#",end="",flush=True)
current_percent = int((received_size / total) * 100 )
new_size = yield
received_size += new_size
def _get(self,cmd_list):
print("get--",cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action':'get',
'filename':cmd_list[1]
}
if self.__md5_required(cmd_list):
data_header['md5'] = True self.sock.send(json.dumps(data_header).encode())
response = self.get_response()
print(response)
if response["status_code"] ==257:#ready to receive
self.sock.send(b'')#send confirmation to server
base_filename = cmd_list[1].split('/')[-1]
received_size = 0
file_obj = open(base_filename,"wb")
if self.__md5_required(cmd_list):
md5_obj = hashlib.md5()
progress = self.show_progress(response['file_size']) #generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
file_obj.write(data)
md5_obj.update(data)
else:
print("----->file rece done----")
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['status_code'] == 258:
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!" % base_filename)
#print(md5_val,md5_from_server) else:
progress = self.show_progress(response['file_size']) #generator
progress.__next__() while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
file_obj.write(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%") else:
print("----->file recv done----")
file_obj.close()
def _put(self,cmd_list):
print("put----",cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action':'put',
'filename':cmd_list[1]
}
self.sock.send(json.dumps(data_header).encode())
#response = self.get_response()
#print(response)
print("client......")
file_obj = open(cmd_list[1],"rb")
file_size = os.stat(cmd_list[1]).st_size
print(file_size)
self.sock.send(str(file_size).encode())
self.sock.recv(1024) #等待服务端确认
progress = self.show_progress(file_size) # generator
progress.__next__()
for i in file_obj:
self.sock.send(i)
else:
try:
progress.send(int(file_size))
except StopIteration as e:
print("100%")
file_obj.close()
print("send done...")
if __name__ == "__main__":
ftp = FTPClient()
ftp.interactive() #交互

ftp_client

Python网络编程学习_Day9的更多相关文章

  1. python网络编程学习《一》

    最近,刚实习完,很喜欢实验楼,但是自己的方向仍然不能确定,自己觉得可选择的空间很大,尽管已经是大四的人了,想到别人都在忙着买职业装,买高跟鞋面试,学习化妆什么的,看看自己,反而开始慢慢关注运动,食疗以 ...

  2. python网络编程学习笔记(三):socket网络服务器(转载)

    1.TCP连接的建立方法 客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较. 步骤 TCP客户端 TCP服务器 第一步 建立socket对象  建立socket对 ...

  3. Python网络编程学习_Day11

    一.协程 1.理论知识 协程,又称伪线程,是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈. ...

  4. Python网络编程学习_Day10

    一.进程与线程 1.区别 进程:一个程序要运行时所需要的所有资源的集合,进程是资源的集合. 一个进程至少需要一个线程,这个线程称为主线程 一个进程里面可以有多个线程 两个进程之间的数据是完全独立,不能 ...

  5. python网络编程学习笔记(10):webpy框架

    转载请注明:@小五义http://www.cnblogs.com/xiaowuyi django和webpy都是python的web开发框架.Django的主要目的是简便.快速的开发数据库驱动的网站. ...

  6. Python网络编程基础|百度网盘免费下载|零基础入门学习资料

    百度网盘免费下载:Python网络编程基础|零基础学习资料 提取码:k7a1 目录: 第1部分 底层网络 第1章 客户/服务器网络介绍 第2章 网络客户端 第3章 网络服务器 第4章 域名系统 第5章 ...

  7. Python学习(22)python网络编程

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

  8. 《Python网络编程》学习笔记--使用谷歌地理编码API获取一个JSON文档

    Foundations of Python Network Programing,Third Edition <python网络编程>,本书中的代码可在Github上搜索fopnp下载 本 ...

  9. Python 网络编程相关知识学习

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

随机推荐

  1. 订单处理(c#实现)

    State模式的经典应用场景:订单处理(c#实现) State模式在对象内部状态发生变化的时候,改变自身的行为,这通常是通过切换内部状态对象实现的,对象将自身在各个状态的行为推给了状态对象,从而解开了 ...

  2. 学点c++

    描述现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复:还知道这个长方形的宽和长,编号.长.宽都是整数:现在要求按照一下方式排序(默认排序规则都是从小到大): 1.按照编号从小到大排序 2. ...

  3. AngularJS的工作原理1

    AngularJS的工作原理 个人觉得,要很好的理解AngularJS的运行机制,才能尽可能避免掉到坑里面去.在这篇文章中,我将根据网上的资料和自己的理解对AngularJS的在启动后,每一步都做了些 ...

  4. spring mvc在普通类中获取HttpServletRequest对象

    如题,需要在web.xml中配置request监听,如下 <listener> <description>spring request监听器</description&g ...

  5. NuGet安装及简单使用

    通过Visual Studio安装NuGet 直接下载并安装NuGet 一.通过Visual Studio安装NuGet 打开Visual Studio扩展管理器 2.选择联机库,并在搜索中写入NuG ...

  6. Solr与MongoDB集成,实时增量索引

    Solr与MongoDB集成,实时增量索引 一. 概述 大量的数据存储在MongoDB上,需要快速搜索出目标内容,于是搭建Solr服务. 另外一点,用Solr索引数据后,可以把数据用在不同的项目当中, ...

  7. 自由的Debian

    原文:http://www.debian.org/intro/free 许多人在刚开始接触自由软件时都会很困惑,原因是自由软件中的自由一词并不是他们所期望的那样.对他们而言自由意味着免费.一本英文字典 ...

  8. 1047找环环&1503整数探究

    1047就是判断一个数乘以他的位数1~n后是这个数转来转去的一个形式.主要就是大整数乘法 贴shi代码 #include<iostream> #include<string> ...

  9. AspNetWebApi管线中如果定义两种类型的消息处理程序(全局/路由)

    AspNetWebApi管线中如果定义两种类型的消息处理程序(全局/路由) 在AspNetWebApi管线中存在两种类型的消息处理程序(Message Handler) 1.全局消息处理程序,所有的请 ...

  10. 使用 App Studio 快速定制一个你自己的专属应用

    使用 App Studio 快速定制一个你自己的专属应用 如果已有做一个手机应用的想法,只需要一些简单的图片,视频,或者RSS源,就可以通过App Studio制作出你心仪的应用! App Studi ...