# 這里邊是一個定義了服務端的一系列函式,是Python網路編程這本書第七章的第一個例子,
# 這是供后邊函式進行呼叫了,然后我們來進行研究網路的單執行緒編程,多執行緒編程、異步網路編程等,
# 匯入網路編程socket、時間time、cmd引數獲取模塊
import argparse, socket, time
# 定義一個字典用來存放發送給客戶端的訊息,
aphorisms = {b'Beautiful is better than?': b'Ugly.',
b'Explicit is better than?': b'Implicit.',
b'Simple is better than?': b'Complex.'}
# 獲取答案, 如果客戶端發送了問題,就從上邊的字典里邊獲取,如果沒有的話就回傳我不知道的錯誤,
def get_answer(aphorism):
"""Return the string response to a particular Zen-of-Python aphorism."""
time.sleep(0.0) # increase to simulate an expensive operation
return aphorisms.get(aphorism, b'Error: unknown aphorism.')
# 定義一個函式用來獲取終端需要傳入的引數, host:主機IP或者名稱 -p:埠,默認為1060
# 回傳值是一個元祖,包含IP埠,
def parse_command_line(description):
"""Parse command line and return a socket address."""
parser = argparse.ArgumentParser(description=description)
parser.add_argument('host', help='IP or hostname')
parser.add_argument('-p', metavar='port', type=int, default=1060,
help='TCP port (default 1060)')
args = parser.parse_args()
address = (args.host, args.p)
return address
# 創造一個socket套接字,這里的入參是上邊那個函式的出參,
def create_srv_socket(address):
"""Build and return a listening server socket."""
# 創造一個套接字,
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設定,
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 服務端系結IP和埠,
listener.bind(address)
# 設定服務端能夠監聽的數量,這里設定的是最大能夠同時監聽64個,
listener.listen(64)
# 列印出系結的IP埠,服務端系結的,
print('Listening at {}'.format(address))
# 回傳這個套接字,
return listener
# 一直持續不斷的進行監聽, 觀察有沒有客戶端和服務端進行連接,
# 這里的入參是上邊函式的出參
def accept_connections_forever(listener):
"""Forever answer incoming connections on a listening socket."""
# 死回圈
while True:
# 服務端一直在監聽埠,看有沒有客戶端進行連接,
# 這個是阻塞的,如果有的話那么才會進行下邊的操作,
sock, address = listener.accept()
# 列印出客戶端IP埠
print('Accepted connection from {}'.format(address))
handle_conversation(sock, address)
# 處理連接對話函式,
def handle_conversation(sock, address):
"""Converse with a client over `sock` until they are done talking."""
try:
while True:
# 這里一直處理客戶端的請求,
handle_request(sock)
# 接收例外,代表著客戶端斷開了連接,
except EOFError:
print('Client socket to {} has closed'.format(address))
# 如果有其他錯誤,我們也需要進行接收下來,
except Exception as e:
print('Client {} error: {}'.format(address, e))
# 最后關閉服務端的套接字,
finally:
sock.close()
# 處理請求函式,
def handle_request(sock):
"""Receive a single client request on `sock` and send the answer."""
# 這里我們呼叫函式進行接收客戶端發送過來的訊息,
aphorism = recv_until(sock, b'?')
# 然后呼叫獲取答案函式,將我們的答案回復給客戶端,
answer = get_answer(aphorism)
# 服務端進行發送訊息
sock.sendall(answer)
# 服務端和客戶端進行連接后,一直進行接收客戶端發送過來的訊息,直到客戶端發送了suffix
# 這里我們的入參為?,如果客戶端發送了suffix就代表著客戶端發送完了訊息,就需要進行關閉了,
def recv_until(sock, suffix):
"""Receive bytes over socket `sock` until we receive the `suffix`."""
# 接收資料,
message = sock.recv(4096)
# 如果資料為空,就拋出一個連接關閉的錯誤,
if not message:
raise EOFError('socket closed')
# 判斷接收的訊息最后是否是suffix,如果是地話,那我們就直接反悔了,
# 如果不是,就代表著客戶端還有資料進行發送,服務端就需要繼續進行接收,
while not message.endswith(suffix):
# 能夠進來while回圈,就代表著客戶端還有資料進行發送,
# 那么我們需要繼續進行接收
data = https://www.cnblogs.com/cong12586/p/sock.recv(4096)
# 如果客戶端的資料為空,
# 再次拋出一個例外,
if not data:
raise IOError('received {!r} then socket closed'.format(message))
message += data
# 回傳接收的資料,
return message
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/228398.html
標籤:Python
上一篇:02select監聽客戶端
下一篇:爬小說
