20190323 Pyhton網路程式設計

2021-09-13 12:52:50 字數 2700 閱讀 9863

網際網路協議包含了上百種協議標準,但是最重要的兩個協議是tcp和ip協議,所以,大家把網際網路的協議簡稱tcp/ip協議。

ip協議負責把資料從一台計算機通過網路傳送到另一台計算機。資料被分割成一小塊一小塊,然後通過ip包傳送出去。由於網際網路鏈路複雜,兩台計算機之間經常有多條線路,因此,路由器就負責決定如何把乙個ip包**出去。ip包的特點是按塊傳送,途徑多個路由,但不保證能到達,也不保證順序到達。

tcp協議則是建立在ip協議之上的。tcp協議負責在兩台計算機之間建立可靠連線,保證資料報按順序到達。tcp協議會通過握手建立連線,然後,對每個ip包編號,確保對方按順序收到,如果包丟掉了,就自動重發。

許多常用的更高階的協議都是建立在tcp協議基礎上的,比如用於瀏覽器的http協議、傳送郵件的smtp協議等。

乙個tcp報文除了包含要傳輸的資料外,還包含源ip位址和目標ip位址,源埠和目標埠。

埠有什麼作用?在兩台計算機通訊時,只發ip位址是不夠的,因為同一臺計算機上跑著多個網路程式。乙個tcp報文來了之後,到底是交給瀏覽器還是qq,就需要埠號來區分。每個網路程式都向作業系統申請唯一的埠號,這樣,兩個程序在兩台計算機之間建立網路連線就需要各自的ip位址和各自的埠號。ip位址決定了交給哪個電腦,而埠號是決定交給哪個程序。

tcp程式設計

大多數連線都是可靠的tcp連線。建立tcp連線時,主動發起連線的叫客戶端,被動響應連線的叫伺服器。在這裡插入**片

所以,我們要建立乙個基於tcp連線的socket,可以這樣做:

# 匯入socket庫:

import socket

# 建立乙個socket:

s = socket.socket(socket.af_inet, socket.sock_stream)

# 建立連線:

s.connect(('www.sina.com.cn', 80))

建立socket,af_inet指定適應ipv4協議,如果想要使用更為先進的ipv6,就指定為af_inet6。

sock_stream指定使用面向流的tcp協議,這樣,乙個socket物件就建立成功,但是還是沒有建立鏈結。

s.connect(('www.sina.com.cn', 80))
注意引數是乙個tuple,包含位址和埠號。

s.send(b'get / http/1.1\r\nhost: www.sina.com.cn\r\nconnection: close\r\n\r\n')
伺服器

伺服器程序首先要繫結乙個埠並監聽來自其他客戶端的連線。如果某個客戶端連線過來了,伺服器就與該客戶端建立socket連線,隨後的通訊就靠這個socket連線了。

所以,伺服器會開啟固定埠(比如80)監聽,每來乙個客戶端連線,就建立該socket連線。由於伺服器會有大量來自客戶端的連線,所以,伺服器要能夠區分乙個socket連線是和哪個客戶端繫結的。乙個socket依賴4項:伺服器位址、伺服器端口、客戶端位址、客戶端埠來唯一確定乙個socket。

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

我們來編寫乙個簡單的伺服器程式,它接收客戶端連線,把客戶端發過來的字串加上hello再發回去。

埠號需要預先指定。因為我們寫的這個服務不是標準服務,所以用9999這個埠號。請注意,小於1024的埠號必須要有管理員許可權才能繫結:

# 監聽埠:

s.bind(('127.0.0.1', 9999))

緊接著,呼叫listen()方法開始監聽埠,傳入的引數指定等待連線的最大數量:

s.listen(5)

print('waiting for connection...')

接下來,伺服器程式通過乙個永久迴圈來接受來自客戶端的連線,accept()會等待並返回乙個客戶端的連線:

while true:

# 接受乙個新連線:

sock, addr = s.accept()

# 建立新執行緒來處理tcp連線:

t = threading.thread(target=tcplink, args=(sock, addr))

t.start()

每個連線都必須建立新執行緒(或程序)來處理,否則,單執行緒在處理連線的過程中,無法接受其他客戶端的連線:

ef tcplink(sock, addr):

print('accept new connection from %s:%s...' % addr)

sock.send(b'welcome!')

while true:

data = sock.recv(1024)

time.sleep(1)

if not data or data.decode('utf-8') == 'exit':

break

sock.send(('hello, %s!' % data.decode('utf-8')).encode('utf-8'))

sock.close()

print('connection from %s:%s closed.' % addr)

要測試這個伺服器程式,我們還需要編寫乙個客戶端程式:

linux 網路程式設計與 windows 網路程式設計

最近寫了乙個程式,涉及到在windows下執行的乙個程式到執行在linux下的伺服器取出資料。一開始還真沒有適應過來。下面說說我遇見的一些問題。1 windows下connect不成功。最開始也是不清楚 出錯,程式莫名其妙就在這個connect斷下,而且會花費很長的時間在connect這一句停留很長...

資料幀和網路編址

資料幀和網路編址 資料幀 1 ip報文頭部資訊用於指導網路裝置對報文進行路由和分片。2 同乙個網段 內的資料 通過鏈路層即可實現 單播,組播,廣播 而跨網段的資料 需要使用網路裝置的路由功能。3 分片是指資料報超過一定長度時,需要被劃分成不同 的片段使其能夠在網路中傳輸。4 ip報文頭部長度為20到...

TCP IP網路編學習筆記 三

可以設定tcp或udp通訊的輸入緩衝大小和輸出緩衝大小,但是最終大小並不一定是你所設定的大小 如果服務端先close,或者說先發出fin訊息表示分手,則服務端斷開連線後,在短時間內無法再次bind相同的埠,因為上一次繫結此埠的socket處於time wait過程中,還未被銷毀 不過此時客戶端是沒有...