W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
你想實現(xiàn)一個基于UDP協(xié)議的服務(wù)器來與客戶端通信。
跟TCP一樣,UDP服務(wù)器也可以通過使用?<span class="pre" style="box-sizing: border-box;">socketserver</span>
?庫很容易的被創(chuàng)建。 例如,下面是一個簡單的時間服務(wù)器:
from socketserver import BaseRequestHandler, UDPServer
import time
class TimeHandler(BaseRequestHandler):
def handle(self):
print('Got connection from', self.client_address)
# Get message and client socket
msg, sock = self.request
resp = time.ctime()
sock.sendto(resp.encode('ascii'), self.client_address)
if __name__ == '__main__':
serv = UDPServer(('', 20000), TimeHandler)
serv.serve_forever()
跟之前一樣,你先定義一個實現(xiàn)?<span class="pre" style="box-sizing: border-box;">handle()</span>
?特殊方法的類,為客戶端連接服務(wù)。 這個類的?<span class="pre" style="box-sizing: border-box;">request</span>
屬性是一個包含了數(shù)據(jù)報和底層socket對象的元組。<span class="pre" style="box-sizing: border-box;">client_address</span>
?包含了客戶端地址。
我們來測試下這個服務(wù)器,首先運(yùn)行它,然后打開另外一個Python進(jìn)程向服務(wù)器發(fā)送消息:
>>> from socket import socket, AF_INET, SOCK_DGRAM
>>> s = socket(AF_INET, SOCK_DGRAM)
>>> s.sendto(b'', ('localhost', 20000))
0
>>> s.recvfrom(8192)
(b'Wed Aug 15 20:35:08 2012', ('127.0.0.1', 20000))
>>>
一個典型的UPD服務(wù)器接收到達(dá)的數(shù)據(jù)報(消息)和客戶端地址。如果服務(wù)器需要做應(yīng)答, 它要給客戶端回發(fā)一個數(shù)據(jù)報。對于數(shù)據(jù)報的傳送, 你應(yīng)該使用socket的?<span class="pre" style="box-sizing: border-box;">sendto()</span>
?和?<span class="pre" style="box-sizing: border-box;">recvfrom()</span>
?方法。 盡管傳統(tǒng)的?<span class="pre" style="box-sizing: border-box;">send()</span>
?和?<span class="pre" style="box-sizing: border-box;">recv()</span>
?也可以達(dá)到同樣的效果, 但是前面的兩個方法對于UDP連接而言更普遍。
由于沒有底層的連接,UPD服務(wù)器相對于TCP服務(wù)器來講實現(xiàn)起來更加簡單。 不過,UDP天生是不可靠的(因為通信沒有建立連接,消息可能丟失)。 因此需要由你自己來決定該怎樣處理丟失消息的情況。這個已經(jīng)不在本書討論范圍內(nèi)了, 不過通常來說,如果可靠性對于你程序很重要,你需要借助于序列號、重試、超時以及一些其他方法來保證。 UDP通常被用在那些對于可靠傳輸要求不是很高的場合。例如,在實時應(yīng)用如多媒體流以及游戲領(lǐng)域, 無需返回恢復(fù)丟失的數(shù)據(jù)包(程序只需簡單的忽略它并繼續(xù)向前運(yùn)行)。
<span class="pre" style="box-sizing: border-box;">UDPServer</span>
?類是單線程的,也就是說一次只能為一個客戶端連接服務(wù)。 實際使用中,這個無論是對于UDP還是TCP都不是什么大問題。 如果你想要并發(fā)操作,可以實例化一個?<span class="pre" style="box-sizing: border-box;">ForkingUDPServer</span>
?或<span class="pre" style="box-sizing: border-box;">ThreadingUDPServer</span>
?對象:
from socketserver import ThreadingUDPServer
if __name__ == '__main__':
serv = ThreadingUDPServer(('',20000), TimeHandler)
serv.serve_forever()
直接使用?<span class="pre" style="box-sizing: border-box;">socket</span>
?來是想一個UDP服務(wù)器也不難,下面是一個例子:
from socket import socket, AF_INET, SOCK_DGRAM
import time
def time_server(address):
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(address)
while True:
msg, addr = sock.recvfrom(8192)
print('Got message from', addr)
resp = time.ctime()
sock.sendto(resp.encode('ascii'), addr)
if __name__ == '__main__':
time_server(('', 20000))
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: