網路程式設計通過tcp協議進行聊天對話
網路程式設計
自從網際網路誕生以來,現在基本上所有的程式都是網路程式,很少有單機版的程式了。
計算機網路就是把各個計算機連線到一起,讓網路中的計算機可以互相通訊。網路程式設計就是如何在程式中實現兩臺計算機的通訊。
網路程式設計對所有開發語言都是一樣的,Python也不例外。用Python進行網路程式設計,就是在Python程式本身這個程序內,連線別的伺服器程序的通訊埠進行通訊。
基本概念
IP地址實際上是一個32位整數(稱為IPv4),以字串表示的IP地址如192.168.0.1實際上是把32位整數按8位分組後的數字表示,目的是便於閱讀。
IPv6地址實際上是一個128位整數,它是目前使用的IPv4的升級版,以字串表示類似於2001:0db8:85a3:0042:1000:8a2e:0370:7334。
TCP協議則是建立在IP協議之上的。TCP協議負責在兩臺計算機之間建立可靠連線,保證資料包按順序到達。TCP協議會通過握手建立連線,然後,對每個IP包編號,確保對方按順序收到,如果包丟掉了,就自動重發。
許多常用的更高階的協議都是建立在TCP協議基礎上的,比如用於瀏覽器的HTTP協議、傳送郵件的SMTP協議等。
一個TCP報文除了包含要傳輸的資料外,還包含源IP地址和目標IP地址,源埠和目標埠。
埠有什麼作用?在兩臺計算機通訊時,只發IP地址是不夠的,因為同一臺計算機上跑著多個網路程式。一個TCP報文來了之後,到底是交給瀏覽器還是QQ,就需要埠號來區分。每個網路程式都向作業系統申請唯一的埠號,這樣,兩個程序在兩臺計算機之間建立網路連線就需要各自的IP地址和各自的埠號。
一個程序也可能同時與多個計算機建立連結,因此它會申請很多埠。
TCP程式設計
什麼是 Socket?
Socket又稱”套接字”,應用程式通常通過”套接字”向網路發出請求或者應答網路請求,使主機間或者一臺計算機上的程序間可以通訊。
socket()函式
Python中,我們用socket()函式來建立套接字。
Socket物件(內建)主要方法
伺服器端套接字
s.bind() 繫結地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
s.listen() 開始TCP監聽。backlog指定在拒絕連線之前,作業系統可以掛起的最大連線數量。該值至少為1,大部分應用程式設為5就可以了。
s.accept() 被動接受TCP客戶端連線,(阻塞式)等待連線的到來
客戶端套接字
s.connect() 主動初始化TCP伺服器連線,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
s.connect_ex() connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常
公共用途套接字函式
s.recv() 接收TCP資料,資料以字串形式返回,bufsize指定要接收的最大資料量。flag提供有關訊息的其他資訊,通常可以忽略。
s.send() 傳送TCP資料,將string中的資料傳送到連線的套接字。返回值是要傳送的位元組數量,該數量可能小於string的位元組大小。
s.close() 關閉套接字
伺服器
和客戶端程式設計相比,伺服器程式設計就要複雜一些。
伺服器程序首先要繫結一個埠並監聽來自其他客戶端的連線。如果某個客戶端連線過來了,伺服器就與該客戶端建立Socket連線,隨後的通訊就靠這個Socket連線了。
所以,伺服器會開啟固定埠(比如80)監聽,每來一個客戶端連線,就建立該Socket連線。由於伺服器會有大量來自客戶端的連線,所以,伺服器要能夠區分一個Socket連線是和哪個客戶端繫結的。一個Socket依賴4項:伺服器地址、伺服器埠、客戶端地址、客戶端埠來唯一確定一個Socket。
但是伺服器還需要同時響應多個客戶端的請求,所以,每個連線都需要一個新的程序或者新的執行緒來處理,否則,伺服器一次就只能服務一個客戶端了。
例
#匯入 socket和_thread模組
import socket
import _thread
#建立socket物件
serverSocket=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
#獲取本地主機名和埠號
serverSocket.bind(("localhost",8888))
print("伺服器等待。。。")
#設定最大連線數,超過後排隊
serverSocket.listen(5)
#serverSocket.accpet()會返回兩個值一個是客戶端例項另一個是客戶端地址ip
clientSocket,addr=serverSocket.accept()
#進行多執行緒獲取客戶端內容
def jieshoumsg():
while True:
#接收小於1024位元組的資料並編碼成utf-8格式
msg = clientSocket.recv(1024).decode("utf-8")
print("客戶端說:", msg)
_thread.start_new_thread(jieshoumsg,())
#進行多執行緒對客戶端傳送內容
def sendqq():
while True:
qq=input("我說:")
#傳送資料並解析成utf-8格式
clientSocket.send(qq.encode("utf-8"))
_thread.start_new_thread(sendqq(),())
客戶端
大多數連線都是可靠的TCP連線。建立TCP連線時,主動發起連線的叫客戶端,被動響應連線的叫伺服器。
import socket
import _thread
#建立Socket物件
clientSocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#連線指定的服務端 和埠
clientSocket.connect(("localhost",8888))
print("客戶端連線")
#下面就跟伺服器的一樣了
def jieshoumsg():
while True:
msg = clientSocket.recv(1024).decode("utf-8")
print("伺服器說:", msg)
_thread.start_new_thread(jieshoumsg,())
def sendqq():
while True:
qq=input("我說")
clientSocket.send(qq.encode("utf-8"))
_thread.start_new_thread(sendqq(),())