尝试用最短的Python代码来实现服务器和代理服务器

一个最简单的服务器Python拥有这种单独起一个服务器监听端口的能力,用标准库的wsgiref就行。

?

12345678from wsgiref.simple_server import make_server def simple_app(environ, start_response):  status = 200 OK  response_headers = [(Content-type,text/plain)]  start_response(status, response_headers)  return [Hello world!\n] httpd = make_server(, 80, simple_app) httpd.serve_forever()

50行代码实现代理服务器之前遇到一个场景是这样的:我在自己的电脑上需要用mongodb图形客户端,但是mongodb的服务器地址没有对外网开放,只能通过先登录主机A,然后再从A连接mongodb服务器B。本来想通过ssh端口转发的,但是我没有从机器A连接ssh到B的权限。于是就自己用Python写一个。原理很简单。1.开一个socket server监听连接请求2.每接受一个客户端的连接请求,就往要转发的地址建一条连接请求。即client->proxy->forward。proxy既是socket服务端(监听client),也是socket客户端(往forward请求)。3.把client->proxy和proxy->forward这2条socket用字典给绑定起来。4.通过这个映射的字典把send/recv到的数据原封不动的传递下面上代码。

?

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#coding=utf-8 import socket import select import sys to_addr = (xxx.xxx.xx.xxx, 10000)#转发的地址 class Proxy:  def __init__(self, addr):    self.proxy = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    self.proxy.bind(addr)    self.proxy.listen(10)    self.inputs = [self.proxy]    self.route = {}  def serve_forever(self):    print proxy listen...    while 1:      readable, _, _ = select.select(self.inputs, [], [])      for self.sock in readable:        if self.sock == self.proxy:          self.on_join()        else:          data = self.sock.recv(8096)          if not data:            self.on_quit()          else:            self.route[self.sock].send(data)  def on_join(self):    client, addr = self.proxy.accept()    print addr,connect    forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    forward.connect(to_addr)    self.inputs += [client, forward]    self.route[client] = forward    self.route[forward] = client  def on_quit(self):    for s in self.sock, self.route[self.sock]:      self.inputs.remove(s)      del self.route[s]      s.close() if __name__ == __main__:  try:    Proxy((,12345)).serve_forever()#代理服务器监听的地址  except KeyboardInterrupt:    sys.exit(1)

效果截图如下。