python实战--Http代理服务器
打算好好深入研究下pytho的socket编程,那天看了这篇博文,http://www.apprk.com/archives/146,于是打算学习下,仿写了一下,发现写好还真不容易,中途出现很多问题,果真是看的容易,做起来难啊。
源代码如下:
import socket
import thread
import urlparse
import select BUFLEN=8192 class Proxy(object):
def __init__(self,conn,addr):
self.source=conn
self.request=""
self.headers={}
self.destnation=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.run() def get_headers(self):
header=''
while True:
header+=self.source.recv(BUFLEN)
index=header.find('\n')
if index >0:
break
#firstLine,self.request=header.split('\r\n',1)
firstLine=header[:index]
self.request=header[index+1:]
self.headers['method'],self.headers['path'],self.headers['protocol']=firstLine.split() def conn_destnation(self):
url=urlparse.urlparse(self.headers['path'])
hostname=url[1]
port="80"
if hostname.find(':') >0:
addr,port=hostname.split(':')
else:
addr=hostname
port=int(port)
ip=socket.gethostbyname(addr)
print ip,port
self.destnation.connect((ip,port))
data="%s %s %s\r\n" %(self.headers['method'],self.headers['path'],self.headers['protocol'])
self.destnation.send(data+self.request)
print data+self.request def renderto(self):
readsocket=[self.destnation]
while True:
data=''
(rlist,wlist,elist)=select.select(readsocket,[],[],3)
if rlist:
data=rlist[0].recv(BUFLEN)
if len(data)>0:
self.source.send(data)
else:
break
def run(self):
self.get_headers()
self.conn_destnation()
self.renderto() class Server(object): def __init__(self,host,port,handler=Proxy):
self.host=host
self.port=port
self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind((host,port))
self.server.listen(5)
self.handler=handler def start(self):
while True:
try:
conn,addr=self.server.accept()
thread.start_new_thread(self.handler,(conn,addr))
except:
pass if __name__=='__main__':
s=Server('127.0.0.1',8080)
s.start()
其实Http代理服务器本身不难,但写出来还是挺费事的,这里就不细说源代码了,很简单。主要说说,我遇到的问题。
一: 我本来只知道,thread.start_new_thread的第一个参数是函数对象,但当我看到上面的博文时,心里一愣,这样也可以,于是我迅速的测试了一下:
import thread class Hello:
def __init__(self,content):
print content def cs():
thread.start_new_thread(Hello, ("Hello World",)) if __name__=='__main__':
cs()
我很失望的发现,报了个异常
Unhandled exception in thread started by
Error in sys.excepthook: Original exception was:
一看,我说嘛,第一个参数怎么可以是对象,我呵呵一笑,稍微鄙视了一下作者。于是,我洗洗睡了,第二天,我还是不死心,于是把代码下下来,本地实验了一下,可以的,立马意识到是我2了,于是立马百度。
原来thread模块中,主线程如果比子线程先结束,就会抛出这个异常,所以我们必须让子线程先结束,最简单的方法就是让主线程sleep足够长的时间,至于多长时间,貌似不知道,那到底怎么解决呢?
比较好的解决办法就是,主线程给每个子线程都加一把锁,子线程在结束前将锁释放掉,主线程一直循环检查锁的状态。代码如下:
import thread class Hello:
def __init__(self,content,lock):
print content
"""
do something
....
At the end,release the lock
"""
lock.release() def cs():
lock=thread.allocate_lock()
lock.acquire()
thread.start_new_thread(Hello, ("Hello World",lock))
while True:
if not lock.locked():
break
print "lock release" if __name__=='__main__':
cs()
结果如下:
Hello World
lock release
二.第二个错误就是比较2的了
self.source.send[data]
TypeError: 'builtin_function_or_method' object is unsubscriptable
主要是单词unsubscriptable不认识,呵呵,单词不认识,伤不起啊。
主要意思就是说,内置函数或方法无法拥有下标,你懂的,错的很2很2。
python实战--Http代理服务器的更多相关文章
- zeromq 学习和python实战
参考文档: 官网 http://zeromq.org/ http://www.cnblogs.com/rainbowzc/p/3357594.html 原理解读 zeromq只是一层针对socke ...
- Python实战:美女图片下载器,海量图片任你下载
Python应用现在如火如荼,应用范围很广.因其效率高开发迅速的优势,快速进入编程语言排行榜前几名.本系列文章致力于可以全面系统的介绍Python语言开发知识和相关知识总结.希望大家能够快速入门并学习 ...
- Python实战:Python爬虫学习教程,获取电影排行榜
Python应用现在如火如荼,应用范围很广.因其效率高开发迅速的优势,快速进入编程语言排行榜前几名.本系列文章致力于可以全面系统的介绍Python语言开发知识和相关知识总结.希望大家能够快速入门并学习 ...
- python实战--数据结构二叉树
此文将讲述如何用python实战解决二叉树实验 前面已经讲述了python语言的基本用法,现在让我们实战一下具体明确python的用法 点击我进入python速成笔记 先看一下最终效果图: 首先我们要 ...
- 再一波Python实战项目列表
前言: 近几年Python可谓是大热啊,很多人都纷纷投入Python的学习中,以前我们实验楼总结过多篇Python实战项目列表,不但有用还有趣,最主要的是咱们实验楼不但有详细的开发教程,更有在线开发环 ...
- python实战:用70行代码写了一个山炮计算器!
python实战训练:用70行代码写了个山炮计算器! 好了...好了...各位因为我是三年级而发牢骚的各位伙伴们,我第一次为大家插播了python的基础实战训练.这个,我是想给,那些python基础一 ...
- python实战博客
2018-10-31 更新Logging日志记录以及异常捕获 感谢廖大教程.Python实战 直接在闲置的服务器上开发.阿里云Centos 6.8 64位. 1 搭建开发环境 Python 环境是Py ...
- python实战提升--1
#python实战提升 1. 如何在列表.字典.集合中根据条件筛选数据? python中for _ in range(10)与for i in range(10)有何区别 下划线表示 临时变量, 仅用 ...
- 原创:centos7.1下 ZooKeeper 集群安装配置+Python实战范例
centos7.1下 ZooKeeper 集群安装配置+Python实战范例 下载:http://apache.fayea.com/zookeeper/zookeeper-3.4.9/zookeepe ...
随机推荐
- networkRequest
void TPHttp::applyResource(){ QJsonObject json; json.insert("ProductCode","MoVd ...
- Mybatis 学习
1. Mybatis 中 # 与 $ 符号的区别: a. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号. 如:order by #user_id#,如果传入的值是12,那么解 ...
- hdu 4452
今天模拟赛的一个模拟题: 每次看到这种题就感觉很繁琐: 这次静下心来写写,感觉还不错!就是很多错误,浪费了一点时间: 代码: #include<cstdio> #include<cs ...
- ThinkPHP3.1快速入门(3)查询语言
http://www.thinkphp.cn/info/115.html 介绍 ThinkPHP内置了非常灵活的查询方法,可以快速的进行数据查询操作,查询条件可以用于读取.更新和删除等操作,主要涉及到 ...
- [ecmall]Ecmall 后台添加模板编辑区
例如,想把品牌/index.php?app=brand页面做成可编辑的. 首先,找到后台admin\includes\menu.inc.php第61行 'template' => array( ...
- PHP 中的随机数——你觉得可靠么?
本文主要分析以加密为目的的随机数生成问题.PHP 5 并未提供生成强加密随机数的简便机制,但是,PHP 7 引入了两个 CSPRNG 函数以解决该问题.系 OneAPM 工程师编译整理. 什么是 CS ...
- 如何配置svn服务器(通过VisualServer服务器)
如果你已经安装好了VisualServer服务器,现在让我们一起来配置svn服务器吧
- Makefile第二讲:打印出内容和使用变量
摘要 `@echo "开始生成最终执行文件,请稍候..."`这一句便是将一条信息输出到终端,为何前边有个`@`符号呢?有了这个符号该命令本身就不会输出到终端(不理解,自己去掉或者加 ...
- devi into python 笔记(三)callable getattr lambda表达式
常用的函数:callable():如果所给参数是可调用的,返回True 不可调用返回Fasle.这里指的是否能调用说的是方法.类方法等有doc string的东西,一个单纯的字符串等就不算了. imp ...
- 图片上传,支持同步/异步、预览(MVC、uploadify异步提交、js预览、ajaxSubmit异步提交)兼容大部分浏览器,含代码
图片上传代码,支持同步/异步和图片的预览 主要用了两种方式,可兼容大部分浏览器. 第一种使用uploadify异步上传,上传后返回图片路径显示到页面. 每二种使用ajaxSubmit异步上传,为兼容I ...