Socket編程
1.基本概念
1.什么是客戶端/服務器架構?
服務器就是一系列硬件或軟件,為一個或多個客戶端(服務的用戶)提供所需的“服務”。
它存在唯一目的就是等待客戶端的請求,
并響應它們(提供服務),然后等待更多請求。
說白了就是一個提供服務,一個請求服務得到相應的一個過程。
2.套接字:通信端點
套接字是計算機網絡數據結構,它體現了上節中描述的“通信端點”的概念。
在任何類型的通信開始之前,網絡應用程序必須創建套接字。
可以將它們比作電話插孔,沒有它將無法進行通信。
Python只支持AF_UNIX、AF_NETLINK、AF_TIPC 和 AF_INET ,重點使用基于網絡的AF_INET.
3.套接字地址:主機-端口對
它是網絡通信過程中端點的抽象表示,python使用元組保存:ADDR = (HOST,PORT)。
4.套接字類型
流式套接字(SOCK_STREAM):用于提供面向連接、可靠的數據傳輸服務。
數據報套接字(SOCK_DGRAM):提供了一種無連接的服務。
該服務并不能保證數據傳輸的可靠性,數據有可能在傳輸過程中丟失或出現數據重復,且無法保證順序地接收到數據。
2.Python網絡編程
2.1 常見的套接字對象方法和屬性
2.2 創建服務和客戶端
2.2.1 創建TCP服務
一般的創建流程:
ss = socket() # 創建服務器套接字
ss.bind(ADDR) # 套接字與地址綁定
ss.listen() # 監聽連接
while True: # 服務器無限循環
cs = ss.accept() # 接受客戶端連接
comm_loop: # 通信循環
cs.recv()/cs.send() # 對話(接收 / 發送)
cs.close() # 關閉客戶端套接字
ss.close() # 關閉服務器套接字 # (可選)
2.2.2 創建 TCP 客戶端
一般的創建流程:
cs = socket() # 創建客戶端套接字
cs.connect() # 嘗試連接服務器
comm_loop: # 通信循環
cs.send()/cs.recv() # 對話(發送 / 接收)
cs.close() # 關閉客戶端套接字
2.2.3 創建UDP服務
一般的創建流程:
ss = socket() # 創建服務器套接字
ss.bind(ADDR) # 套接字與地址綁定
while True: # 服務器無限循環
ss.sendto() # 發送
ss.recvfrom() # 接收
ss.close() # 關閉服務器套接字 # (可選)
2.2.4 創建 UDP 客戶端
一般的創建流程:
cs = socket() # 創建客戶端套接字
comm_loop: # 通信循環
cs.sendto() # 發送
cs.recvfrom() # 接收
cs.close() # 關閉客戶端套接字
server.py代碼
import socket
from time import ctime
import json
import time
HOST = ''
PORT = 9001
ADDR = (HOST, PORT)
BUFFSIZE = 1024
MAX_LISTEN = 5
def tcpServer():
# TCP服務
# with socket.socket() as s:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# 綁定服務器地址和端口
s.bind(ADDR)
# 啟動服務監聽
s.listen(MAX_LISTEN)
print('等待用戶接入。。。。。。。。。。。。')
while True:
# 等待客戶端連接請求,獲取connSock
conn, addr = s.accept()
print('警告,遠端客戶:{} 接入系統!!!'.format(addr))
with conn:
while True:
print('接收請求信息。。。。。')
# 接收請求信息
data = conn.recv(BUFFSIZE)
print('data=%s' % data)
print('接收數據:{!r}'.format(data.decode('utf-8')))
# 發送請求數據
conn.send(data.encode('utf-8'))
print('發送返回完畢!!!')
s.close()
# 創建UDP服務
def udpServer():
# 創建UPD服務端套接字
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
# 綁定地址和端口
s.bind(ADDR)
# 等待接收信息
while True:
print('UDP服務啟動,準備接收數據。。。')
# 接收數據和客戶端請求地址
data, address = s.recvfrom(BUFFSIZE)
if not data:
break
print('接收請求信息:{}'.format(data.decode('utf-8')))
s.sendto(b'i am udp,i got it', address)
s.close()
if __name__ == '__main__':
while True:
choice = input('input choice t-tcp or u-udp:')
if choice != 't' and choice != 'u':
print('please input t or u,ok?')
continue
if choice == 't':
print('execute tcpsever')
tcpServer()
else:
print('execute udpsever')
udpServer()
client.py代碼
import socket
from time import ctime
HOST = 'localhost'
PORT = 9001
ADDR = (HOST, PORT)
ENCODING = 'utf-8'
BUFFSIZE = 1024
def tcpClient():
# 創建客戶套接字
with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as s:
# 嘗試連接服務器
s.connect(ADDR)
print('連接服務成功!!')
# 通信循環
while True:
inData = input('pleace input something:')
if inData == 'q':
break
# 發送數據到服務器
inData = '[{}]:{}'.format(ctime(), inData)
s.send(inData.encode(ENCODING))
print('發送成功!')
# 接收返回數據
outData = s.recv(BUFFSIZE)
print('返回數據信息:{!r}'.format(outData))
# 關閉客戶端套接字
s.close()
def udpClient():
# 創建客戶端套接字
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
while True:
# 發送信息到服務器
data = input('please input message to server or input \'quit\':')
if data == 'quit':
break
data = '[{}]:{}'.format(ctime(), data)
s.sendto(data.encode('utf-8'), ADDR)
print('send success')
# 接收服務端返回信息
recvData, addrs = s.recvfrom(BUFFSIZE)
print('recv message : {}'.format(recvData.decode('utf-8')))
# 關閉套接字
s.close()
if __name__ == '__main__':
while True:
choice = input('input choice t-tcp or u-udp or q-quit:')
if choice == 'q':
break
if choice != 't' and choice != 'u':
print('please input t or u,ok?')
continue
if choice == 't':
print('execute tcpsever')
tcpClient()
else:
print('execute udpsever')
udpClient()
代碼說明:先執行 python server.py,在執行python client.py,就可以測試TPC/UDP簡單的通信了。