NAT的分类:在STUN协议中,根据内部终端的地址(LocalIP:LocalPort)到NAT出口的公网地址(PublicIP:PublicPort)的影射方式,把NAT分为四种类型(英文原文详见rfc3489标准:http://www.ietf.org/rfc/rfc3489.txt): |
由于存在有4种NAT的类型,所以在方案设计中,必须要考虑到用哪种软件或者设备来模拟NAT环境。我在实现过程中尝试过了很多选择,包括Linux下的iptables,海蜘蛛的软路由,使用CISCO的IOS模拟,window2003自带的NAT服务,还有VMWARE自带的NAT网络环境。最终发现window2003和VMWARE是支持full cone nat的。 |
#!/usr/bin/python
#coding:utf-8
import socket, sys, SocketServer, threading, thread, time
SERVER_PORT = 1234
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', SERVER_PORT))
user_list = []
def server_handle():
whileTrue:
cli_date, cli_pub_add = sock.recvfrom(8192)
now_user = []
headder = []
cli_str = {}
headder = cli_date.split('\t')
for one_line in headder:
str = {}
str = one_line
args = str.split(':')
cli_str[args[0]] = args[1]
if cli_str['type'] == 'login' :
del cli_str['type']
now_user = cli_str
now_user['cli_pub_ip'] = cli_pub_add[0]
now_user['cli_pub_port'] = cli_pub_add[1]
user_list.append(now_user)
toclient = 'info#%s login in successful , the info from server'%now_user['user_name']
sock.sendto(toclient,cli_pub_add)
print'-'*100
print"%s 已经登录,公网IP:%s 端口:%d\n"%(now_user['user_name'],now_user['cli_pub_ip'],now_user['cli_pub_port'])
print"以下是已经登录的用户列表"
for one_user in user_list:
print'用户名:%s 公网ip:%s 公网端口:%s 私网ip:%s 私网端口:%s'%(one_user['user_name'],one_user['cli_pub_ip'],one_user['cli_pub_port'],one_user['private_ip'],one_user['private_port'])
elif cli_str['type'] == 'alive':
pass
elif cli_str['type'] == 'logout' :
pass
elif cli_str['type'] == 'getalluser' :
print'-'*100
for one_user in user_list :
toclient = 'getalluser#username:%s pub_ip:%s pub_port:%s pri_ip:%s pri_port:%s'%(one_user['user_name'],one_user['cli_pub_ip'],one_user['cli_pub_port'],one_user['private_ip'],one_user['private_port'])
sock.sendto(toclient,cli_pub_add)
if __name__ == '__main__':
thread.start_new_thread(server_handle, ())
print'服务器进程已启动,等待客户连接'
whileTrue:
for one_user in user_list:
toclient = 'keepconnect#111'
sock.sendto(toclient,(one_user['cli_pub_ip'],one_user['cli_pub_port']))
time.sleep(1)
#!/usr/bin/python
#coding:utf-8
import socket, SocketServer, threading, thread, time
CLIENT_PORT = 4321
SERVER_IP = "200.0.0.128"
SERVER_PORT = 1234
user_list = {}
local_ip = socket.gethostbyname(socket.gethostname())
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def server_handle():
print'客户端线程已经启动 , 等待其它客户端连接'
whileTrue:
data, addr = sock.recvfrom(8192)
data_str = data.split('#')
data_type = data_str[0]
data_info = data_str[1]
if data_type == 'info' :
del data_str[0]
print data_info
if data_type == 'getalluser' :
data_sp = data_info.split(' ')
user_name = data_sp[0].split(':')[1]
del data_sp[0]
user_list[user_name] = {}
for one_line in data_sp:
arg = one_line.split(':')
user_list[user_name][arg[0]] = arg[1]
if data_type == 'echo' :
print data_info
if data_type == 'keepconnect':
messeg = 'type:alive'
sock.sendto(messeg, addr)
if __name__ == '__main__':
thread.start_new_thread(server_handle, ())
time.sleep(0.1)
cmd = raw_input('输入指令>>')
whileTrue:
args = cmd.split(' ')
if args[0] == 'login':
user_name = args[1]
local_uname = args[1]
address = "private_ip:%s private_port:%d" % (local_ip, CLIENT_PORT)
headder = "type:login\tuser_name:%s\tprivate_ip:%s\tprivate_port:%d" % (user_name,local_ip,CLIENT_PORT)
sock.sendto(headder, (SERVER_IP, SERVER_PORT))
elif args[0] == 'getalluser':
headder = "type:getalluser\tuser_name:al"
sock.sendto(headder,(SERVER_IP,SERVER_PORT))
print'获取用户列表中。。。'
time.sleep(1)
for one_user in user_list:
print'username:%s pub_ip:%s pub_port:%s pri_ip:%s pri_port:%s'%(one_user,user_list[one_user]['pub_ip'],user_list[one_user]['pub_port'],user_list[one_user]['pri_ip'],user_list[one_user]['pri_port'])
elif args[0] == 'connect':
user_name = args[1]
to_user_ip = user_list[user_name]['pub_ip']
to_user_port = int(user_list[user_name]['pub_port'])
elif args[0] =='echo':
m = ' '.join(args[1:])
messeg = 'echo#from %s:%s'%(local_uname,m)
sock.sendto(messeg, (to_user_ip, to_user_port))
time.sleep(0.1)
cmd = raw_input('输入指令>>')