python实现简单的TCP代理服务器


Posted in Python onOctober 08, 2014

本文实例讲述了python实现简单的TCP代理服务器的方法,分享给大家供大家参考。

具体实现代码如下:

# -*- coding: utf-8 -*-

'''
filename:rtcp.py
@desc:
利用python的socket端口转发,用于远程维护
如果连接不到远程,会sleep 36s,最多尝试200(即两小时)

@usage:
./rtcp.py stream1 stream2
stream为:l:port或c:host:port
l:port表示监听指定的本地端口
c:host:port表示监听远程指定的端口

@author: watercloud, zd, knownsec team
@web: www.knownsec.com, blog.knownsec.com
@date: 2009-7
'''

import socket
import sys
import threading
import time

streams = [None, None] # 存放需要进行数据转发的两个数据流(都是SocketObj对象)
debug = 1 # 调试状态 0 or 1

def _usage():
 print 'Usage: ./rtcp.py stream1 stream2\nstream : l:port or c:host:port'

def _get_another_stream(num):
 '''
 从streams获取另外一个流对象,如果当前为空,则等待
 '''
 if num == 0:
 num = 1
 elif num == 1:
 num = 0
 else:
 raise "ERROR"

 while True:
 if streams[num] == 'quit':
  print("can't connect to the target, quit now!")
  sys.exit(1)

 if streams[num] != None:
  return streams[num]
 else:
  time.sleep(1)

def _xstream(num, s1, s2):
 '''
 交换两个流的数据
 num为当前流编号,主要用于调试目的,区分两个回路状态用。
 '''
 try:
 while True:
  #注意,recv函数会阻塞,直到对端完全关闭(close后还需要一定时间才能关闭,最快关闭方法是shutdow)
  buff = s1.recv(1024)
  if debug > 0:
  print num,"recv"
  if len(buff) == 0: #对端关闭连接,读不到数据
  print num,"one closed"
  break
  s2.sendall(buff)
  if debug > 0:
  print num,"sendall"
 except :
 print num,"one connect closed."

 try:
 s1.shutdown(socket.SHUT_RDWR)
 s1.close()
 except:
 pass

 try:
 s2.shutdown(socket.SHUT_RDWR)
 s2.close()
 except:
 pass

 streams[0] = None
 streams[1] = None
 print num, "CLOSED"

def _server(port, num):
 '''
 处理服务情况,num为流编号(第0号还是第1号)
 '''
 srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 srv.bind(('0.0.0.0', port))
 srv.listen(1)
 while True:
 conn, addr = srv.accept()
 print "connected from:", addr
 streams[num] = conn # 放入本端流对象
 s2 = _get_another_stream(num) # 获取另一端流对象
 _xstream(num, conn, s2)

def _connect(host, port, num):
 ''' 处理连接,num为流编号(第0号还是第1号)

 @note: 如果连接不到远程,会sleep 36s,最多尝试200(即两小时)
 '''
 not_connet_time = 0
 wait_time = 36
 try_cnt = 199
 while True:
 if not_connet_time > try_cnt:
  streams[num] = 'quit'
  print('not connected')
  return None

 conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 try:
  conn.connect((host, port))
 except Exception, e:
  print ('can not connect %s:%s!' % (host, port))
  not_connet_time += 1
  time.sleep(wait_time)
  continue

 print "connected to %s:%i" % (host, port)
 streams[num] = conn #放入本端流对象
 s2 = _get_another_stream(num) #获取另一端流对象
 _xstream(num, conn, s2)


if __name__ == '__main__':
 if len(sys.argv) != 3:
 _usage()
 sys.exit(1)
 tlist = [] # 线程列表,最终存放两个线程对象
 targv = [sys.argv[1], sys.argv[2] ]
 for i in [0, 1]:
 s = targv[i] # stream描述 c:ip:port 或 l:port
 sl = s.split(':')
 if len(sl) == 2 and (sl[0] == 'l' or sl[0] == 'L'): # l:port
  t = threading.Thread(target=_server, args=(int(sl[1]), i))
  tlist.append(t)
 elif len(sl) == 3 and (sl[0] == 'c' or sl[0] == 'C'): # c:host:port
  t = threading.Thread(target=_connect, args=(sl[1], int(sl[2]), i))
  tlist.append(t)
 else:
  _usage()
  sys.exit(1)

 for t in tlist:
 t.start()
 for t in tlist:
 t.join()
 sys.exit(0)

完整实例代码点击此处本站下载。

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
Python修改MP3文件的方法
Jun 15 Python
Python、PyCharm安装及使用方法(Mac版)详解
Apr 28 Python
python smtplib模块自动收发邮件功能(二)
May 22 Python
python中plot实现即时数据动态显示方法
Jun 22 Python
解决使用PyCharm时无法启动控制台的问题
Jan 19 Python
在Django的View中使用asyncio的方法
Jul 12 Python
Python实用库 PrettyTable 学习笔记
Aug 06 Python
Python实现捕获异常发生的文件和具体行数
Apr 25 Python
Python基于模块Paramiko实现SSHv2协议
Apr 28 Python
大数据分析用java还是Python
Jul 06 Python
python 删除excel表格重复行,数据预处理操作
Jul 06 Python
python 实现逻辑回归
Dec 30 Python
python操作CouchDB的方法
Oct 08 #Python
python基于queue和threading实现多线程下载实例
Oct 08 #Python
python实现封装得到virustotal扫描结果
Oct 05 #Python
python解析xml文件操作实例
Oct 05 #Python
python写xml文件的操作实例
Oct 05 #Python
python实现上传样本到virustotal并查询扫描信息的方法
Oct 05 #Python
python实现计算资源图标crc值的方法
Oct 05 #Python
You might like
德劲1104的电路分析与改良
2021/03/01 无线电
PHP字符串的编码问题的详细介绍
2013/04/27 PHP
利用phpexcel把excel导入数据库和数据库导出excel实现
2014/01/09 PHP
详谈PHP程序Laravel 5框架的优化技巧
2016/07/18 PHP
[原创]php token使用与验证示例【测试可用】
2017/08/30 PHP
PHP递归的三种常用方式
2019/02/28 PHP
PHP7 弃用功能
2021/03/09 PHP
jQuery调用WebService的实现代码
2011/06/19 Javascript
jquery 鼠标滑动显示详情应用示例
2014/01/24 Javascript
使用Sticker.js实现贴纸效果
2015/01/28 Javascript
Javascript中拼接大量字符串的方法
2015/02/05 Javascript
jQuery判断一个元素是否可见的方法
2015/06/05 Javascript
不用一句js代码初始化组件
2016/01/27 Javascript
实现JavaScript的组成----BOM和DOM详解
2016/05/18 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
select隐藏选中值对应的id,显示其它id的简单实现方法
2016/08/25 Javascript
JS操作input标签属性checkbox全选的实现代码
2017/03/02 Javascript
vue-cli构建项目使用 less的方法
2017/10/04 Javascript
Vue 与 Vuex 的第一次接触遇到的坑
2018/08/16 Javascript
基于Vue实现可以拖拽的树形表格实例详解
2018/10/18 Javascript
vue-cli3.0如何使用CDN区分开发、生产、预发布环境
2018/11/22 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
[01:04:35]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第一场
2018/04/04 DOTA
Python基于identicon库创建类似Github上用的头像功能
2017/09/25 Python
Python的Tkinter点击按钮触发事件的例子
2019/07/19 Python
python add_argument()用法解析
2020/01/29 Python
解决python3插入mysql时内容带有引号的问题
2020/03/02 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
Html5基于canvas实现电子签名并生成PDF文档
2020/12/07 HTML / CSS
在加拿大在线租赁和购买电子游戏:Game Access
2019/09/02 全球购物
法人代表授权委托书
2014/04/08 职场文书
2014年毕业演讲稿范文
2014/05/13 职场文书
MySQL锁机制
2021/04/05 MySQL
angular异步验证器防抖实例详解
2022/03/31 Javascript
MySQL选择合适的备份策略和备份工具
2022/06/01 MySQL
Windows Server 2012 R2服务器安装与配置的完整步骤
2022/07/15 Servers