1. 程式人生 > >《python核心程式設計》讀書筆記-建立TCP服務端/客戶端

《python核心程式設計》讀書筆記-建立TCP服務端/客戶端

建立套接字

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()

先啟動服務端,然後啟動客戶端

客戶端
在這裡插入圖片描述

服務端
在這裡插入圖片描述