Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Recipe 13.13. Forwarding and Redirecting Network Ports


Credit: Simon Foster


Problem


You need to forward a network port to another host
(forwarding), possibly to a different port
number (redirecting).


Solution


Classes using the tHReading and
socket modules can provide port forwarding and
redirecting:

import sys, socket, time, threading
LOGGING = True
loglock = threading.Lock( )
def log(s, *a):
if LOGGING:
loglock.acquire( )
try:
print '%s:%s' % (time.ctime( ), (s % a))
sys.stdout.flush( )
finally:
loglock.release( )
class PipeThread(threading.Thread):
pipes = [ ]
pipeslock = threading.Lock( )
def _ _init_ _(self, source, sink):
Thread._ _init_ _(self)
self.source = source
self.sink = sink
log('Creating new pipe thread %s ( %s -> %s )',
self, source.getpeername( ), sink.getpeername( ))
self.pipeslock.acquire( )
try: self.pipes.append(self)
finally: self.pipeslock.release( )
self.pipeslock.acquire( )
try: pipes_now = len(self.pipes)
finally: self.pipeslock.release( )
log('%s pipes now active', pipes_now)
def run(self):
while True:
try:
data = self.source.recv(1024)
if not data: break
self.sink.send(data)
except:
break
log('%s terminating', self)
self.pipeslock.acquire( )
try: self.pipes.remove(self)
finally: self.pipeslock.release( )
self.pipeslock.acquire( )
try: pipes_left = len(self.pipes)
finally: self.pipeslock.release( )
log('%s pipes still active', pipes_left)
class Pinhole(threading.Thread):
def _ _init_ _(self, port, newhost, newport):
Thread._ _init_ _(self)
log('Redirecting: localhost:%s -> %s:%s', port, newhost, newport)
self.newhost = newhost
self.newport = newport
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(('', port))
self.sock.listen(5)
def run(self):
while True:
newsock, address = self.sock.accept( )
log('Creating new session for %s:%s', *address)
fwd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
fwd.connect((self.newhost, self.newport))
PipeThread(newsock, fwd).start( )
PipeThread(fwd, newsock).start( )

A short ending to this pinhole.py module, with
the usual guard to run this part only when pinhole
is run as a main script rather than imported, lets us offer this
recipe's functionality as a command-line script:

if _ _name_ _ == '_ _main_ _':
print 'Starting Pinhole port forwarder/redirector'
import sys
# get the arguments, give help in case of errors
try:
port = int(sys.argv[1])
newhost = sys.argv[2]
try: newport = int(sys.argv[3])
except IndexError: newport = port
except (ValueError, IndexError):
print 'Usage: %s port newhost [newport]' % sys.argv[0]
sys.exit(1)
# start operations
sys.stdout = open('pinhole.log', 'w')
Pinhole(port, newhost, newport).start( )


Discussion


Port forwarding and redirecting can often come in handy when
you're operating a network, even a small one.
Applications or other services, possibly not under your control, may
be hardwired to connect to servers on certain addresses or ports; by
interposing a forwarder and redirector, you can send such
applications' connection requests onto any other
host and/or port that suits you better.

The code in this recipe supplies two classes that liberally use
threading to provide this functionality and a small
"main script" at the end, with the
usual if _ _name_ _ = = '_ _main_ _' guard, to
deliver this functionality as a command-line script. For once, the
small "main script" is not just for
demonstration and testing purposes but is actually quite useful on
its own. For example:

# python pinhole.py 80 webserver

forwards all incoming HTTP sessions on standard port 80 to host
webserver;

# python pinhole.py 23 localhost 2323

redirects all incoming telnet sessions on standard
port 23 to port 2323 on this same host (since
localhost is the conventional hostname for
"this host" in all TCP/IP
implementations).


See Also


Documentation for the standard library modules
socket and threading in the
Library Reference and Python in a
Nutshell
.


/ 394