1、从语言的选择方向来说,因为我目的是要方便生活使用,希望能快速达到目的,如果用C和C++来说,工作量稍大些,于是选择了我还算熟悉的python语言
2、里面比较有意思的是在于数据的转发,代理既要承担“送出去”的任务,也要承担“送回来”的任务,思考了下数据结构的使用,使用了字典的方式,即client->forward,forward->client,如果用C来实现的话,就是封装一个结构体,里边有客户端连接的socket,也有传送回来的forward sokcet
3、一旦接收到有客户端连接代理程序,代理程序马上向要转发的目的机器进行TCP连接的建立,同时将双方的socket信息成对保存在字典中
4、采用简单的select模型,主要是图个便利,当有活动的socket连接时,能马上检测到socket句柄的活动,从而从字典中找到对应的socket连接信息
总结:既然选择了写程序,碰到看不顺手,或操作麻烦的事情,就来个程序终结它,Orz!
技术没有所谓最好的语言,语言只是工具,但要用好,别伤了自己,在合理的事情上选择对的工具,让那些争论PHP是最好的语言的人浪费时间去吧。最后:上程序!!叮叮叮!
#coding=utf-8 import socket import select import sys import threading import time import logging import os logsDir = "logs" #目录不存在则创建 if not os.path.isdir(logsDir): os.mkdir(logsDir) #记录日志 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='logs/logs.log', filemode='a') #C的IP和端口 to_addr = () #最大连接数 maxConnetions = 32 class Proxy: def __init__(self, addr): self.proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.proxy.bind(addr) self.proxy.listen(maxConnetions) self.inputs = {self.proxy:None} self.route = {} def serve_forever(self): logging.info('proxy listen...') while 1: readable, _, _ = select.select(list(self.inputs.keys()), [], []) for self.sock in readable: if self.sock == self.proxy: self.on_join() else: try: data = self.sock.recv(8192) except Exception, e: logging.error(str(e)) self.on_quit() continue if not data: self.on_quit() else: try: self.route[self.sock].send(data) except Exception, e: logging.error(str(e)) self.on_quit() continue def on_join(self): client, addr = self.proxy.accept() logging.info("proxy client " + str(addr) + 'connect') forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: forward.connect(to_addr) except Exception, e: logging.error(str(e)) client.close() return self.inputs [client] = None self.inputs [forward] = None self.route[client] = forward self.route[forward] = client #删除连接 def on_quit(self): ls = [self.sock] if self.sock in self.route: ls.append(self.route[self.sock]) for s in ls: if s in self.inputs: del self.inputs展开 if s in self.route: del self.route展开 s.close() if __name__ == '__main__': proxy = Proxy(('',54321)) try: with open('proxy.conf',"r") as fd: info_list = fd.readline().split(',') to_addr = (info_list[0],int(info_list[1])) print to_addr proxy.serve_forever()#代理服务器监听的地址 except KeyboardInterrupt: sys.exit(1)
最后,我用pyinstaller生成了一个可执行的二进制程序,使用说明都在里边了
- 微信扫码赞助
- 支付宝赞助