網絡編程
Ubuntu命令
查看ip: ifconfig
ping 查看網絡連通性
ping 127.0.0.1 檢查網絡功能是否正常
ping 本機網卡IP地址 檢查網卡是否正常工作
ping 遠程主機IP/域名 檢查與遠程主機的連通性
端口基礎
定義:系統分配給網絡應用程序的編號,用來區分數據傳輸
網絡程序必須要有端口號
知名端口號0-1023
動態端口號 1024-65535
檢驗指定端口網絡連接情況:netstat -an | grep ":8080"
列出當前系統端口所對應的程序: lsof -i [tcp/udp]:8080
擴展: netstat -anp | grep ":8080" 查看指定端口的程序網絡連接情況
擴展: ps -aux | grep "python" 查看python的程序
擴展: kill -9 進程的PID 關閉進程
UDP
特點
- 無需確認對端是否存在,發送端隨時可發送數據
- 無連接、資源開銷小、速度塊、單個數據包最大爲64K
- 傳輸不可靠,容易丟失數據
- 沒有流量控制,所有接受方需及時接收數據,否則會出現緩衝過慢,電腦卡死
使用場景
- 音樂視頻傳輸
- 廣播
- 主要用在通訊質量要求不高的場景
創建步驟
客戶端:初始化,指定ip端口sendto發送,recvform接受,close關閉
#創建一個udp_licent #初始化,ipv4,指定udp模式,綁定端口 #發送數據 #接受數據 #關閉套接字對象 import socket import time def main(): #初始化 udp_licent = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #發送數據 udp_licent.sendto("要發送的數據".encode("utf-8"),('127.0.0.1',8080)) #接受數據 info = udp_licent.recvfrom(1024) # 每次接受1024個字節數據 print(info[0].decode("utf-8")) info = udp_licent.recvfrom(1024) #每次接受1024個字節數據 print(info[0].decode("utf-8")) # 接受到的數據爲二進制數據進行解碼 #關閉對象 udp_licent.close() time.sleep(1) if __name__ == '__main__': while True: main()
服務端:初始化、端口複用、綁定端口、廣播模式、接受、發送(廣播模式255地址進行廣播)、關閉#創建一個udp_server #初始化 #複用端口 #綁定端口 #設置廣播模式 #響應客戶端 #接受數據 #發送數據 #關閉套接字 import socket def main(): #初始化 udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #複用端口 udp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) #設置廣播模式,發送時指定255.255.255.255 udp_server.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,True) #綁定端口 udp_server.bind(('',8080)) #接受數據,收到數據爲一個元組,0下標元素爲數據,1號下標爲發送者地址與端口 info = udp_server.recvfrom(1024) #每次接受1024個字節數據 #接受數據時阻塞程序 print(".............程序被阻塞.................") #發送者地址信息 news="收到:%s"%info[0].decode("utf-8") print(news) #發送數據,使用接受到的信息可以給發送者回復 udp_server.sendto(news.encode("utf-8"),info[1]) #使用255.255.255.255地址可以進行廣播發送,此時簡寫成發送者的端口 #實際進行廣播時,客戶端要設置成與客戶端廣播一致的端口 udp_server.sendto("進行廣播".encode("utf-8"),('255.255.255.255',info[1][1])) #關閉服務器套接字 udp_server.close() if __name__ == '__main__': while True: main()
TCP
概述
- 面向連接的、可靠的、基於字節流的傳輸層通信協議.
特點
- TCP通信需要經過創建連接、數據傳送、終止連接三個步驟。
- 先建立連接纔可以進行數據傳輸,雙方都必須爲該連接分配必要的系統內核資源,以管理連接的狀態和連接上的傳輸可靠傳輸,採用發送應答機制,超時重傳,錯誤校驗,流量控制和阻塞管理
創建步驟
客戶端:初始化、connect連接、send發送、recv接受,close關閉
import socket # 創建tcp socket tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 目的信息 server_ip = input("請輸入服務器ip:") server_port = int(input("請輸入服務器port:")) # 鏈接服務器 tcp_client_socket.connect((server_ip, server_port)) # 提示用戶輸入數據 send_data = input("請輸入要發送的數據:") tcp_client_socket.send(send_data.encode("gbk")) # 接收對方發送過來的數據,最大接收1024個字節 recvData = tcp_client_socket.recv(1024) print('接收到的數據爲:', recvData.decode('gbk')) # 關閉套接字 tcp_client_socket.close()
服務端:初始化、端口複用、綁定端口、監聽模式、建立連接生成服務對象、服務對象send發送、服務對象recv接受、關閉服務 對象、關閉服務端import socket # 創建socket tcp_server_socket = socket(socket.AF_INET, socket.SOCK_STREAM) # 本地信息 address = ('', 7788) # 綁定 tcp_server_socket.bind(address) # 設置監聽 # 使用socket創建的套接字默認的屬性是主動的,使用listen將其變爲被動的,這樣就可以接收別人的鏈接了 # 128:表示最大等待連接數 tcp_server_socket.listen(128) # 如果有新的客戶端來鏈接服務器,那麼就產生一個新的套接字專門爲這個客戶端服務 # client_socket用來爲這個客戶端服務 # tcp_server_socket就可以省下來專門等待其他新客戶端的鏈接 client_socket, clientAddr = tcp_server_socket.accept() # 接收對方發送過來的數據 recv_data = client_socket.recv(1024) # 接收1024個字節 print('接收到的數據爲:', recv_data.decode('gbk')) # 發送一些數據到客戶端 client_socket.send("thank you !".encode('gbk')) # 關閉爲這個客戶端服務的套接字,只要關閉了,就意味着爲不能再爲這個客戶端服務了,如果還需要服務,只能再次重新連接 client_socket.close()
UDP和TCP的區別
- TCP面向連接不支持廣播,UDP不是面向連接支持廣播式
- TCP需要連接,提供可靠數據傳輸且按序到達,但傳輸速度慢,UDP不需要連接,不保證可靠傳輸,但速度快
- TCP適合發送大量數據,有流量控制,UDP適合發少量數據,沒有流量控制
文件下載器示例代碼
TCP服務端 參考代碼如下:
import socket
import os
if __name__ == '__main__':
# 創建tcp服務端socket
tcp_serve_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置socket選項,防止程序退出端口不立即釋放的問題
tcp_serve_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 綁定端口
tcp_serve_socket.bind(("", 9090))
# 設置監聽,把主動套接字改成被動套接字,被動套接字只能接收客戶端的連接請求,不能收發消息
tcp_serve_socket.listen(128)
# 循環接收客戶端的連接請求, 提示:現在的下載是同步下載,一個用戶下載完成以後另外一個用戶才能下載
while True:
# 接收客戶端的連接請求
service_client_socket, ip_port = tcp_serve_socket.accept()
# 代碼執行到說明解阻塞,說明連接建立成功
file_name_data = service_client_socket.recv(1024)
# 解碼數據
file_name = file_name_data.decode("gbk")
print(file_name, ip_port)
if os.path.exists(file_name):
# 文件存在
with open(file_name, "rb") as file:
# 讀取文件數據
while True:
file_data = file.read(1024)
if file_data:
# 發送文件數據給客戶端
service_client_socket.send(file_data)
else:
break
else:
print("文件不存在")
# 終止和客戶端服務
service_client_socket.close()
# 終止提供處理連接請的服務
tcp_serve_socket.close()
TCP客戶端 參考代碼如下:
import socket
if __name__ == '__main__':
# 創建tcp客戶端socket
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接
tcp_client_socket.connect(("192.168.107.160", 9090))
# 獲取用戶輸入文件名
file_name = input("請輸入您要下載的文件名:")
# 使用gbk進行編碼
file_name_data = file_name.encode("gbk")
# 代碼執行到此,說明連接建立成功
tcp_client_socket.send(file_name_data)
with open("/home/python/Desktop/" + file_name, "wb") as file:
# 循環接收服務端發送的文件二進制數據
while True:
# 獲取服務端文件數據
file_data = tcp_client_socket.recv(1024)
if file_data:
# 寫入到指定文件
file.write(file_data)
else:
break
# 關閉socket
tcp_client_socket.close()