既然有了一个Open×××的前端控制程序,那么就可以在一台机器上启动多个Open×××实例了,不同的客户端只要连接不同的实例就好。事实证明,这种方式可以完美利用多处理器的优势,比在Open×××内部实现的多进程或者多线程等多处理方式要好很多,这也是广义的KISS原则,也遵循了“每次做好一件事”的原则。
        现在的关键问题是如何将这多个Open×××实例集合在一起作为一个整体。既然Open×××使用了更底层的虚拟网卡技术,那么做这件事的技术也和这些底层技术有关了,我试了下bridge方式,非常不错,bridge在Linux上的实现非常棒,工具也很齐全,不过一个brctl够了。方法是,将多个Open×××服务端实例的tap网卡bridge在一起,这样它们就可以共享一个IP地址了,也就可以使用同一个地址段了,剩下的事情,由bridge来完成吧!
        我的bridge-multi×××实现使用“预生成实例”的方式,也就是预先生成一组Open×××服务端实例,生成多少由CPU的个数决定,一般生成“CPU*2-2”个即可,我还是相信“操作系统的调度要比Open×××本身的调度做得好”...当然也可以使用“每客户端一例”的方式,不过那样对于管理不是很方便,具体也没有测试。
#!/usr/bin/python #coding=gbk  import signal import socket   import sys import os   def signal_handler(signal, frame):     os.popen("goaway.sh")     sys.exit(0)  if __name__ == '__main__':       signal.signal(signal.SIGINT, signal_handler)     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)       sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)     sock.bind(('0.0.0.0', 61195))       sock.listen(1024)            # 起始端口     minport = 6119     # 结束端口     maxport = 6125     # 起始虚拟IP地址分量     minsubnet = 2     delta = 8     currport = minport     # 启动(maxport-minport)个Open×××实例,侦听不同的端口,分配不同的地址段     while currport <= maxport:         if currport == maxport:             cmd =     "open*** --config"\                 " server.conf"\                 " --up createBR.sh"\                 " --port %s"\                 " --ifconfig-pool 10.8.0.%s 10.8.0.%s 255.255.255.0"\                 % (currport, minsubnet, minsubnet+delta)                      else:             cmd =     "/root/open***-ipv6/open*** --config"\                 " /root/open***-ipv6/server.conf"\                 " --port %s"\                 " --ifconfig-pool 10.8.0.%s 10.8.0.%s 255.255.255.0"\                 % (currport, minsubnet, minsubnet+delta)         os.popen(cmd)         print cmd         currport = currport + 1         minsubnet = minsubnet + delta + 1     currport = minport     while True:           connection,address = sock.accept()           try:               connection.settimeout(5)               buf = connection.recv(1024)               if buf == 'getport':                   # 按照轮转的方式为客户端分配Open×××实例                 connection.send(str(currport))                 currport = currport + 1                 if currport > maxport:                       currport = minport         except socket.timeout:               os.popen("goaway.sh")             print 'time out'           connection.close()       os.popen("goaway.sh")

最后一个Open×××的虚拟网卡启动的时候,调用createBR.sh,将所有的虚拟网卡和bridge联系起来:
#!/bin/bash  # 获取服务端的IP地址,实际只需要第一个,因为大家最终都一样 virtual_GW=$(ifconfig tap0|awk -F 'inet addr:' '/inet addr/{print $2}'|awk -F ' ' '{print $1}');  # 创建一个bridge brctl addbr virtual_BR;  # 将各个虚拟网卡陆续添加到bridge for virtual_interface in $(ifconfig |grep -o tap[0-9]); do         brctl addif virtual_BR $virtual_interface;         # 清除已经有的地址         ifconfig $virtual_interface 0.0.0.0; done;  # 将地址赋予bridge ifconfig virtual_BR $virtual_GW up

类似的,清理程序goaway.sh:
killall -9 open*** ifconfig virtual_BR down brctl delbr virtual_BR
服务端的配置文件:
daemon ×××S
script-security 2
mode server
tls-server
tls-cipher RC4-MD5
cipher BF-CBC
duplicate-cn
dev tap
proto udp
keepalive 10 60
# 配置本地的虚拟地址
ifconfig 10.8.0.1 255.255.255.0

local 0.0.0.0
# 留给server.py去设置,多个实例设置成不同的
;port 6119
verb 4
dh dh1024.pem.dh.confca CA.cer
cert A.pem
key  A.key

客户端的前端程序:

#!/usr/bin/python #coding=gbk if __name__ == '__main__':           import socket           import os           sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)           sock.connect(('192.168.2.249', 61195))           # 请求连接端口         sock.send('getport')         # 接收连接端口         port = sock.recv(1024)           sock.close()         # 根据服务器的建议,启动Open×××客户端实例         cmd = 'open*** --config client.conf --remote 192.168.2.249 %s ' % (port)         os.popen(cmd)