1. 程式人生 > >網路程式設計進行客戶端和伺服器的連線

網路程式設計進行客戶端和伺服器的連線

網路程式設計 
自從網際網路誕生以來,現在基本上所有的程式都是網路程式,很少有單機版的程式了。

計算機網路就是把各個計算機連線到一起,讓網路中的計算機可以互相通訊。網路程式設計就是如何在程式中實現兩臺計算機的通訊。

網路程式設計對所有開發語言都是一樣的,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。

但是伺服器還需要同時響應多個客戶端的請求,所以,每個連線都需要一個新的程序或者新的執行緒來處理,否則,伺服器一次就只能服務一個客戶端了。

伺服器:
import socket
#伺服器端
severSocket=socket.socket(
    family=socket.AF_INET,
    type=socket.SOCK_STREAM)
severSocket.bind(("192.168.0.140",7772))
print("伺服器等待。。。。")
severSocket.listen(5)
clienSocket,addr=severSocket.accept()
print(clienSocket)
print(addr)
while True:
   msg=input("伺服器輸入:")
   clienSocket.send(msg.encode("utf-8"))
   msg=clienSocket.recv(1024).decode("utf-8")
print(msg)
clienSocket.close()

客戶端:

import socket

ClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ClientSocket.connect((" 192.168.0.140", 8888))
print("客戶端已經連結")
msg = ClientSocket.recv(1024).decode("utf-8")
print(msg)
ClientSocket.send(b"beybey")
ClientSocket.close()