本文實例講述了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程序設計有所幫助。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
