1. 程式人生 > >網路程式設計通過tcp協議進行聊天對話

網路程式設計通過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(),())