《python核心程式設計》讀書筆記-建立TCP服務端/客戶端
阿新 • • 發佈:2019-01-13
建立套接字
socket()函式
socket(socket_family,socket_type,protocol=0)
#socket_family 是AF_INET或AF_UNIX
#socket_type 套接字型別SOCK_STREAM(TCP型別)或SOCK_DGRAM(UDP型別)
#protocol通常省略,預設為0
建立TCP套接字
tcpSerSock = socket(AF_INET, SOCK_STREAM)
建立UDP套接字
tcpSerSock = socket(AF_INET, SOCK_DGRAM)
常見的套接字物件方法和屬性
伺服器套接字方法
名稱 | 描述 |
---|---|
s.bind() | 將地址(主機號,埠號對)繫結在套接字上 |
s.listen() | 設定並啟動TCP監聽器 |
s.accept() | 被動接受TCP客戶端連線,一直等待直到連線到達 |
客戶端套接字方法
名稱 | 描述 |
---|---|
s.connect() | 主動發起TCP伺服器連線 |
s.connect_ex | connect()的擴充套件版本,此時會以錯誤碼的形式返回問題,而不是丟擲一個異常 |
普通的套接字方法
名稱 | 描述 |
---|---|
s.recv() | 接受TCP訊息 |
s.recv_into() | 接受TCP訊息到指定的緩衝區 |
s.send() | 傳送TCP訊息 |
s.sendall() | 完整的傳送TCP訊息 |
s.recvfrom() | 接受UDP訊息 |
s.recvfrom_into() | 接受UDP訊息到指定緩衝區 |
s.sendto() | 傳送UDP訊息 |
s.getpeername() | 連線到套接字(TCP)的遠端地址 |
s.getsockname() | 當前套接字地址 |
s.getsockopt() | 返回給定套接字選項的值 |
s.setsockopt() | 設定給定套接字選項的值 |
s.shutdown() | 關閉連線 |
s.close() | 關閉套接字 |
s.detach() | 在未關閉檔案描述符的情況下關閉套接字,返回檔案描述符 |
s.ioctl() | 控制套接字的模式(僅window) |
面向阻塞的套接字方法
名稱 | 描述 |
---|---|
s.setblocking() | 設定套接字的阻塞或非阻塞模式 |
s.settimeout() | 設定阻塞套接字操作的超時時間 |
s.gettimeout() | 獲取阻塞套接字操作的超時時間 |
面向檔案的套接字方法
名稱 | 描述 |
---|---|
s.fileno() | 套接字的檔案描述符 |
s.makefile() | 建立與套接字相關的檔案物件 |
資料屬性
名稱 | 描述 |
---|---|
s.family | 套接字家族 |
s.type | 套接字型別 |
s.proto | 套接字協議 |
TCP服務端
這是一個時間戳伺服器,客戶端傳送訊息,服務端接受到之後打上一個時間戳然後返回資訊。
參考《Python核心程式設計》,裡面的測試有一些報錯,下面是調整之後的程式
偽碼
ss = socket() # 建立伺服器套接字
ss.bind() # 套接字與地址繫結
ss.listen() # 監聽連線
inf_loop: # 伺服器無限迴圈
cs = ss.accept() # 接受客戶端連線
comm_loop: # 通訊迴圈
cs.recv()/cs.send() # 對話(接收/傳送)
cs.close() # 關閉客戶端套接字
ss.close() # 關閉伺服器套接字#(可選)
具體實現
[[email protected] ~]# cat tcpserv.py
#!/usr/bin/env python3.4
from socket import * #socket模組不需要下載,自帶了
from time import ctime
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM) #建立TCP套接字
tcpSerSock.bind(ADDR) #將地址繫結在套接字上
tcpSerSock.listen(5) #設定並監聽地址
while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept() #被動接受 TCP 客戶端連線,一直等待直到連線到達(阻塞)
print('...connected from:', addr)
while True:
data = tcpCliSock.recv(BUFSIZE).decode() #接受TCP訊息
if not data:
break
tcpCliSock.send(('[%s] %s' % (ctime(), data)).encode()) #傳送TCP訊息
tcpSerSock.close() #關閉套接字
TCP客戶端
偽碼
cs = socket() # 建立客戶端套接字
cs.connect() # 嘗試連線伺服器
comm_loop: # 通訊迴圈
cs.send()/cs.recv() # 對話(傳送/接收)
cs.close() # 關閉客戶端套接字
具體實現
[[email protected] ~]# cat tcpcli.py
#!/usr/bin/env python3.4
from socket import *
#地址要和服務端相同
HOST = '127.0.0.1'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM) #建立TCP套接字
tcpCliSock.connect(ADDR) #主動發起TCP伺服器連線
while True:
data = input('> ')
if not data:
break
tcpCliSock.send(data.encode()) #傳送TCP訊息
data = tcpCliSock.recv(BUFSIZE).decode() #接受TCP訊息
if not data:
break
print(data)
tcpCliSock.close()
先啟動服務端,然後啟動客戶端
客戶端
服務端