习题16-13
名字服务器。设计并实现一个名字服务器。这个服务器负责维护一个主机名-端口对的数据库,以及一个描述这个服务器提供的服务的字符串。 选择一个或几个服务器到你的名字服务器上进程“注册”。(注意,这时,这些服务器是名字服务器的客户)。每一个客户在启动的时候,都不知道它们想要找的服务器的信息。名字服务器的客户也是这样。这些客户应该发送一个请求到名字服务器,说明它们想要得到什么服务。名字服务器返回一个主机名-端口对给客户,客户这时就可以连到合适的服务器来处理它的请求。
本人想法是这样,这里需要至少三个脚本,一个名字服务器脚本,一个普通服务器脚本,一个客户端脚本。本人理解是,客户端先同名字服务器连接,向名字服务器发送描述服务内容的字符串,而名字服务器根据字符串内容,向客户端返回包含一个普通服务器主机名和端口的字符串,客户端再连接到相应的普通服务器上,来让该普通服务器处理客户端的请求。
题目中说,服务器负责维护一个主机名-端口对的数据库,以及一个描述这个服务器提供的服务的字符串。由于本人还不会数据库的相关知识,这里打算用字典形式,即键是描述该服务器内容的字符串(在脚本中是'ctime'),值是一个包含主机名和端口的元组。
代码如下:
名字服务器脚本
#-*-coding: utf-8-*-
from socket import *
servs = {'ctime': ('localhost', 50007)} # 这里只以连接一个普通服务器为例子
HOST = ''
PORT = 21567
ADDR = (HOST, PORT)
nameServ = socket(AF_INET, SOCK_STREAM)
nameServ.bind(ADDR)
nameServ.listen(5)
while True:
print "nameServ waiting for connection..."
conn, addr = nameServ.accept()
print "Connected by", addr
while True:
data = conn.recv(1024)
if not data:
break
elif data in servs.iterkeys():
respond = str(servs[data]) # 把主机名和端口发送给客户端
else:
respond = "You request is beyond our ability."
conn.sendall(respond)
conn.close()
nameServ.close()
普通服务器脚本
#-*-coding: utf-8-*-
from socket import *
from time import ctime
HOST = 'localhost'
PORT = 50007
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print "waiting for connection..."
tcpCliSock, addr = tcpSerSock.accept()
print "...connected from:", addr
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s] %s' % (ctime(), data))
tcpCliSock.close()
tcpSerSock.close()
客户端脚本
#-*-coding: utf-8-*-
from socket import *
import re
nameServHost = 'localhost'
nameServPort = 21567
ADDR = (nameServHost, nameServPort)
clnt = socket(AF_INET, SOCK_STREAM)
clnt.connect(ADDR) # 先与名字服务器连接
while True:
smsg = raw_input("What can I server you? ")
if not smsg: break
clnt.sendall(smsg)
rmsg = clnt.recv(1024)
if rmsg:
servHost = re.search('[a-z]+', rmsg).group() # 使用正则表达式获取主机名和端口
servPort = int(re.search('\d+', rmsg).group())
break
else:
print "Something wrong occurs."
break
clnt.close()
servclnt = socket(AF_INET, SOCK_STREAM)
servclnt.connect((servHost, servPort)) # 连接到主机名和端口所指向的普通服务器
while True:
sdata = raw_input("Enter anything: ")
if not sdata: break
servclnt.sendall(sdata)
rdata = servclnt.recv(1024)
if not rdata:
break
print rdata
servclnt.close()
附加题(1)和(3)看不懂,(2)就是使用文件把连接信息记录下来就可以了。
本人尚处计算机小白阶段,如果有任何理解有误,恳请指正!