由于UDP服务器不是面向连接的,所以不用像TCP服务器那样做那么多设置工作。事实上,并不用设置什么东西,直接等待进来的连接就好了。
ss = socket() # 创建一个服务器套接字 ss.bind() # 绑定服务器套接字 inf_loop: # 服务器无限循环 cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送) ss.close() # 关闭服务器套接字
|
从伪代码中可以看出,使用的还是那套先创建套接字然后绑定到本地地址(主机/端口对)的方法。无限循环中包含了从客户端接收消息,返回加了时间戳的结果和回去等下一个消息这三步。同样的,由于代码不会跳出无限循环,所以,close()函数调用是可选的。我们写这一句话的原因是要提醒读者,在设计一个更智能的退出方案的时候,要确保close()函数会被调用。
例16.3 UDP时间戳服务器(tsUserv.py)
创建一个能接收客户端消息、在消息前加一个时间戳后返回的UDP服务器。
1 #!/usr/bin/env python 2 3 from socket import * 4 from time import ctime 5 6 HOST='' 7 PORT=21567 8 BUFSIZ = 1024 9 ADDR = (HOST, PORT) 10 11 udpSerSock = socket(AF_INET, SOCK_DGRAM) 12 udpSerSock.bind(ADDR) 13 14 while True: 15 print 'waiting for message...' 16 data, addr = udpSerSock.recvfrom(BUFSIZ) 17 udpSerSock.sendto('[%s] %s' % ( 18 ctime(), data), addr) 19 print '...received from and returned to:', addr 20 21 udpSerSock.close()
|
UDP和TCP服务器的另一个重要的区别是,由于数据报套接字是无连接的,所以无法把客户端连接交给另外的套接字进行后续的通讯。这些服务器只是接受消息,需要的话,给客户端返回一个结果就可以了。
例16.3的tsUserv.py是之前那个TCP服务器的UDP版本,它接收客户端消息,加时间戳后返回给客户端。
逐行解释
1~4行
就像TCP服务器的设置那样,在Unix的启动信息行后,我们导入了time.ctime()函数和socket模块的所有属性。
6~12行
HOST和PORT变量与之前完全一样。socket()函数的调用有一些不同,我们现在要的是一个数据报/UDP的套接字类型。不过bind()函数的调用方式还是跟TCP版本的一样。同样地,由于UDP是无连接的,就不用调用listen()函数来监听进来的连接了。
14~21行
在进入到服务器的无限循环后,我们(被动地)等待(数据报)消息的到来。当有消息进来时,就处理它(在前面加时间戳),把结果返回去,然后再去等待下一个消息。就像之前一样,那个close()函数只是一个演示而已。 |