一、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. mvc日期控件datepick的几篇文章,日后再总结吧

    instinctcoder里有两篇,入门级的 http://instinctcoder.com/asp-net-mvc-4-jquery-datepicker/ http://instinctcode ...

  2. C++ multimap容器访问同一键值元素的不同方法

    multimap是一种多元map容器,允许一个键对应多个值. 本文介绍了 multimap访问同一键值元素的三种不同方法,详细看下面代码: typedef multimap<string,int ...

  3. [转]Libev源码分析 -- 整体设计

    Libev源码分析 -- 整体设计 libev是Marc Lehmann用C写的高性能事件循环库.通过libev,可以灵活地把各种事件组织管理起来,如:时钟.io.信号等.libev在业界内也是广受好 ...

  4. 大IT公司笔试

    都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来了,免得笑话我们这些未出校门的孩纸们,但 ...

  5. 开发者所需要知道的iOS7 SDK新特性

    iOS 7 春风又绿加州岸,物是人非又一年.WWDC 2013 keynote落下帷幕,新的iOS开发旅程也由此开启.在iOS7界面重大变革的背后,开发者们需要知道的又有哪些呢.同去年一样,我会先简单 ...

  6. jquery.validate.unobtrusive.js实现气泡提示mvc错误

    改写jquery.validate.unobtrusive.js实现气泡提示mvc错误 个人对于这个js.css不是很擅长,所以这个气泡提醒的样式网上找了下,用了这个http://www.cnblog ...

  7. UIButton根据不同的状态设置layer

    这需要用到KVO,监听button的highlighted属性的变化,在监听回调里根据监听到得属性值设置layer 设置监听如下 [button  addObserver:self forKeyPat ...

  8. RTB撕开黑盒子 Part 3: Beyond Surplus

    在本文中,我将解释如果要对整个推广计划最大化利润,决定是否应该出价的应该是期望回本率(ROI),而不是期望利润,这与我们以前介绍的有所不同.在Datacratic,我们已经在2012年底切到了基于RO ...

  9. 使用 Spring 2.5 TestContext 测试DAO层

    资源准备:   mysql5.0 spring-2.5  hibernate-3.2  junit-4.jar 创建表 DROP TABLE IF EXISTS `myproject`.`boys`; ...

  10. iOS 开发问题集锦(一)

    最近在QQ群里好多人问一些比较基础的问题,在这罗列一下: 1.键盘上的斜杠键坏掉了,怎么样用快捷键进行注释呢? 首先在Xcode中注释的默认快捷键为:command+/: 其次可以自行修改快捷键:Xc ...