Day-17: 网络编程
---恢復內容開始---
現有的互聯網通訊方式,是服務器端的進程與客戶端進程的通信。Python中進行網絡編程,就是在Python程序本身這個進程內,連接別的服務器進程的通信端口進行通信。
互聯網協議上包含了上百種協議標準,但是,最重要的是兩個協議:TCP和IP協議。所以,互聯網協議簡稱TCP/IP協議。
通信時必須知道雙方的標識,而一臺計算機可能同時接入多個網絡,就會有兩個或多個IP地址。所以,IP地址實際上對應的是計算機的網絡接口,通常是指網卡。
IP協議將數據分割成一小塊一小塊,然后通過IP包發送出去。特點:按塊發送,不保證能到達,也不保證能順序到達。
TCP協議,建立在IP協議上,負責將兩臺計算機之間建立可靠連接,保證數據包按順序到達。
特點:握手連接,對IP包編號,確保順序收到,若掉包,則自動重發。
一個IP包,包含傳輸數據,源IP地址和目標IP地址,源端口和目標端口。
IP是標識在網絡中的電腦的位置,而一臺電腦上會有多個網絡通信進程,所以端口則是標識目標進程在該電腦上的位置。
- TCP編程
首先要理解socket表示“打開一個網絡鏈接”,而創建一個socket需要知道目標計算機中的ip,端口號,然后再指定所用的協議。
客戶端:主動發起鏈接的叫客戶端。
# 導入socket庫: import socket # 創建一個socket: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立連接: s.connect(('www.sina.com.cn', 80))客戶端導入socket庫后首先創建socket網絡鏈接,socket.AF_INET指定使用IPv4協議,socket.AF_INET6指定使用IPv6協議。SOCK_STREAM指定使用面向流的TCP協議。然后輸入所需的ip和端口號,進行鏈接,注:其中域名會自動轉換成ip。
這里指的一提的是:網絡服務小于1024的端口號都是Internet標準服務的端口,有固定的用處,大于1024的則可以任意使用。其中,80端口為網頁服務端口,25為SMTP服務端口,FTP服務為21端口。
# 發送數據: s.send('GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')然后以HTTP格式發送數據,發起請求。
TCP協議只是建立了大致的雙向通道,而至于怎么協調,得依據具體的協議來決定,如HTTP協議規定客戶端必須先發起請求,服務端才能返回數據。
# 接收數據: buffer = [] while True:# 每次最多接收1k字節:d = s.recv(1024)if d:buffer.append(d)else:break data = ''.join(buffer)接受數據時,調用recv(max)方法,指定一次最多接受的字節數,因此,在一個while循環中反復接受,知道recv()返回空數據,表示接收完畢,退出循環。
# 關閉連接: s.close()最后,調用close()方法關閉Socket,一次完整的網絡通信就結束了。
網絡通訊結束后,就可以對接受到的數據進行相應的處理了:
header, html = data.split('\r\n\r\n', 1) print header # 把接收的數據寫入文件: with open('sina.html', 'wb') as f:f.write(html)將HTTP頭和網頁分離一下,把HTTP頭打印出來,網頁內容保存到文件,就得到了新浪的首頁。
服務器:服務器端是提供服務的一方。首先,和客戶端一樣,建立一個socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)客戶端接下來是設置要連接的端口和ip,所以,此時,服務器端要綁定端口和ip:
# 監聽端口: s.bind(('127.0.0.1', 9999))服務器肯能有多塊網卡,也就是多個ip。可以只綁定到一塊網卡的ip地址上;也可以使用0.0.0.0綁定到所有的網絡地址;還可以用127.0.0.1綁定本機地址,此時,就有本機的客戶端才能連接。
接著,調用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()每個連接必須創建一個新的線程(或進程)來處理,不然無法同時應付多個客戶端。
而對于連接之后的處理是,服務器先發送一條歡迎消息,然后等待客戶端數據,并加上Hello再發送給客戶端。如果發送了exit字符串,就直接關閉連接。
相應的測試客戶端程序:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立連接: s.connect(('127.0.0.1', 9999)) # 接收歡迎消息: print s.recv(1024) for data in ['Michael', 'Tracy', 'Sarah']:# 發送數據: s.send(data)print s.recv(1024) s.send('exit') s.close()客戶端和服務端同時運行就可以看到效果:
- UDP編程
TCP是建立可靠的連接,UDP則是面向無連接的協議。使用UDP時,只需要知道對方的IP地址和端口號,不需要建立穩定連接,就可以直接發數據包。但是,能不能到達就不知道了。
它相比于TCP的特點是,速度快,但是不夠穩定可靠,適用于不太重要的連接。
與TCP類似,UDP分為客戶端和服務端。服務器首先需要建立socket,然后綁定端口:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 綁定端口: s.bind(('127.0.0.1', 9999))其中,SOCK_DGRAM指定這個socket的類型是UDP。綁定端口與TCP一樣,但是不需要調用listen()方法,而是直接接收來自任何客戶端的數據:
print 'Bind UDP on 9999...' while True:# 接收數據:data, addr = s.recvfrom(1024)print 'Received from %s:%s.' % addrs.sendto('Hello, %s!' % data, addr)recvfrom()方法返回數據和客戶端的地址與端口。這樣,服務器接收到數據后,就可以直接調用sendto()就可以把數據用UDP發給客戶端。
而客戶端上,首先也是建立socket連接,但是不用建立穩定的連接,所以不要調用connet(),直接通過sendto()將數據傳給服務器。
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for data in ['Michael', 'Tracy', 'Sarah']:# 發送數據:s.sendto(data, ('127.0.0.1', 9999))# 接收數據:print s.recv(1024) s.close()從服務器接收數據仍是調用recv()方法。
效果如圖:
總的來說,UDP不需要建立穩定的連接,所以數據可能不能安全到達,但是速度快。另外,服務器中綁定的UDP端口與TCP端口互不沖突。
?注:本文為學習廖雪峰Python入門整理后的筆記
轉載于:https://www.cnblogs.com/likely-kan/p/7545242.html
總結
以上是生活随笔為你收集整理的Day-17: 网络编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jmeter集合ant进行操作
- 下一篇: 计算机应用基础教程作业脑图 车辆