使用python實現UDP通信方式

python UDP通信

1.打開虛擬通信程序,選擇UDP通信並選定收發數據的ip地址port端口

在這裡插入圖片描述

2.在虛擬機中編寫python程序與主機中的虛擬通信程序實現數據傳輸:

#  註釋的標註格式為:每行開頭則直接輸入#並空一格開始註釋
#  若在每行代碼後面加註釋,則空兩格輸入#再空一格開始註釋
import socket
#  使用udp收發數據
def main():
	#  1.創建socket套接字
	udp_socket = socket.socket(socket.AF_INET, sock.SOCK_DGRAM)  # AF_INET表示使用ipv4,默認不變,SOCK_DGRAM表示使用UDP通信協議
	
	#  2.綁定端口port
	local_addr = ("", 7878)  # 默認本機任何ip ,指定端口號7878
	udp_socket.bind(local_addr)  # 綁定端口
	
	#  3.收發數據
	send_data = input("請輸入您想要發送的數據:" )
	udp_socket.sendto(send_data.encode("utf-8"), ("10.80.34.68", 8080))  # 編碼成全球統一數據格式,用元組表示接收方ip和port
	recv_data = udp_socket.recvfrom(1024)  # 定義單次最大接收字節數
	
	#  4.打印數據
	recv_msg = recv_data[0]  # 接收的元組形式的數據有兩個元素,第一個為發送信息
	send_addr = recv_data[1]  # 元組第二個元素為發信息方的ip以及port
	print ("收到的信息為:", recv_msg.decode("gbk"))  # 默認從windows發出的數據解碼要用”gbk”,保證中文不亂碼
	print ("發送方地址為:", str(send_addr))  # 強轉為字符串輸出地址,保證不亂碼
	
	#  5.關閉套接字
	udp_socket.close()
if __name__ == "__main__":
main()

對UDP協議的理解

Socket簡介

網絡中進程之間如何通信

1,在本地可以通過進程PID來唯一標識一個進程,但是在網絡中這是行不通的。

2,TCP/IP協議族已經幫我們解決瞭這個問題,即:網絡層的ip地址可以唯一標識網絡中的主機;而傳輸層的:協議+端口,可以唯一標識主機中的應用程序(進程)。

3,利用ip地址,協議,端口,就可以標識網絡的進程瞭,網絡中的進程通信就可以利用這個標識與其他進程進行交互。

什麼是Socket?

socket,簡稱:套接字,是進程間通信的一種方式。socket與其他進程間的通信方式不同在於:它能實現不同主機間的進程間通信。例如:QQ聊天、瀏覽網頁、收發Email等等。

創建Socket

在Python中socket模塊的函數socket:

socket.socket(AddressFamily,Type)

加以說明:

函數socket.socket創建一個socket,返回一個socket。

AddressFamily:選擇AF_INET用於網絡中進程間通信或者AF_UNIX用於同一臺機器進程間通信,實際工作中常用AF_INET。

Type:套接字類型,可以是SOCK_STREAM,流式套接字,主要用於tcp協議或者SOCK_DGRAM,數據報套接字,主要用於udp協議。

#import socket
# udp:sock_dgram:數據報套接字
# udpSocket = socket(socket.AF_INET, socket.SOCK_DGRAM)
#
#
# tcp:sock_stream:流式套接字
# tcpSocket = socket(AF_INET, SOCK_STREAM)

UDP特點

UDP:用戶數據報協議,是一個無連接的簡單的面向數據報的運輸層協議。UDP不提供可靠性,它隻是把應用程序傳給IP層的數據報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快。

UDP:是一種面向無連接的協議,每個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網絡上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的

UDP是面向無連接的通訊協議,UDP數據包括目的端口號和源端口號信息,由於通訊不需要連接,所以可以實現廣播發送。

UDP傳輸數據時有大小限制,每個被傳輸的數據報必須限定在64KB之內。

UDP是一個不可靠的協議,發送方所發送的數據報並不一定以相同的次序到達接收方。

UDP一般用於多點通信和實時的數據業務。例如:語音廣播、QQ、視頻會議系統等。

UDP中客戶端和服務器端交互 

UDP中客戶端和服務器端交互

這裡寫圖片描述

服務器端具體實現代碼如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : xiaoke
import socket
# 服務端
def main():
    # 1,創建數據報套接字
    udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2,綁定本地地址,核心是為綁定並公佈端口
    # ''表示指定任意ip:0.0.0.0,系統中任意ip的數據都可以接收
    myAddr = ('', 8080)
    udpSocket.bind(myAddr)
    # 3,接收客戶端數據,獲得客戶端的地址(ip和端口號)
    recData, clientAddr = udpSocket.recvfrom(1024)
    print(clientAddr)
    print(recData.decode())
    # 4,回復客戶端消息
    udpSocket.sendto(recData, clientAddr)
    # 5,關閉socket
    udpSocket.close()
if __name__ == '__main__':
    main()

echo服務器端具體實現代碼如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : xiaoke
import socket
# echo服務端,回射服務器,發過來,彈回去
# 單進程單線程,無連接
def main():
    # 1,創建數據報套接字
    udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2,服務端需要綁定:目的是把端口號和ip地址暴露給別人,讓別人調用
    # 表示指定任意ip:0.0.0.0,系統中任意ip的數據都可以接收
    myAddr = ('', 8080)
    udpSocket.bind(myAddr)
    while True:
        # 3,接收客戶端數據,獲得客戶端的地址(ip和端口號)
        recData, clientAddr = udpSocket.recvfrom(1024)
        # print(clientAddr)
        print(recData.decode())
        # 4,回復客戶端消息
        # udpSocket.sendto(recData, clientAddr)
        sendData = input("服務器!請輸入提供的數據:")
        udpSocket.sendto(sendData.encode(), clientAddr)
    # 5,關閉socket
    udpSocket.close()
if __name__ == '__main__':
    main()

客戶端具體實現代碼如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : xiaoke
import socket
# 客戶端
def main():
    # 1,創建udp類型的socket
    udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2,指定目的地址(ip和端口號
    serverAddr = ('192.168.105.125', 8080)
    while True:
        # 3,發送數據
        sendData = input("客戶端!請輸入請求數據:")
        udpSocket.sendto(sendData.encode(), serverAddr)
        # 4,接收數據是一個元組,本次接收數據的最大長度,建議是2^xxx次方
        receData, peerAddr = udpSocket.recvfrom(1024)
        print(receData.decode())
        # print(peerAddr)
    # 5,關閉socket
    udpSocket.close()
if __name__ == '__main__':
    main()

綁定端口的說明:

1,一般情況下,在電腦上運行的網絡程序有很多,而各自用的端口號很多情況下不知道,為瞭不與其他的網絡程序占用同一個端口號,往往在編程中,udp的端口號一般不綁定。但是如果需要做成一個服務器端的程序的話,是需要綁定的。

2,一個udp網絡程序,可以不綁定端口,此時操作系統會隨機進行分配一個端口,如果重新運行此程序,端口可能會發生變化。

3,一個udp網絡程序,也可以綁定信息(ip地址,端口號),如果綁定成功,那麼操作系統用這個端口號來進行區分收到的網絡數據是否是此進程的。

UDP網絡通信過程 

這裡寫圖片描述

多線程聊天室服務器端的實現

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : xiaoke
import socket
from threading import Thread
def task_recv(s):
    while True:
        recvData, peerAddr = s.recvfrom(1024)
        print('子線程接收:ip地址 %s :  消息 %s' % (str(peerAddr), recvData.decode()))
def task_send(s, addr):
    while True:
        sendData = input('親!請提供返回的數據:')
        s.sendto(sendData.encode(), addr)
def main():
    # 1.創建udp數據報套接字
    serverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2.綁定本地地址,核心是為綁定並公佈端口
    myAddr = ('', 8080)  # ''表示指定任意ip 0.0.0.0 系統中任意ip的數據都可以接收
    serverSocket.bind(myAddr)
    # 3.主線程收到消息,獲得對方的ip,port
    recvData, peerAddr = serverSocket.recvfrom(1024)
    print('主線程接收:ip地址 %s :  消息 %s' % (str(peerAddr), recvData.decode()))
    # 4.啟動接收消息線程
    thread_recv = Thread(target=task_recv, args=(serverSocket,))
    thread_recv.start()
    # 5.再啟動發送消息的線程,傳遞對方的ip port
    thread_send = Thread(target=task_send, args=(serverSocket, peerAddr))
    thread_send.start()
    # 6,等待子線程結束
    thread_recv.join()
    thread_send.join()
if __name__ == "__main__":
    main()

UDP中廣播

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : xiaoke
from socket import *
def main():
    # 1,創建socket,數據報套接字
    udp_socket = socket(AF_INET, SOCK_DGRAM)
    # 2,設置允許廣播
    # 設置socket屬性,是否允許廣播,1就是允許
    udp_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
    # 3,指定廣播地址(“broadcast”,2425)
    broadcast_addr = ('<broadcast>', 8080)
    # 4,發送消息,以下以飛秋軟件演示
    send_data = b'1:100:will:will-pc:32:will broadcast'
    udp_socket.sendto(send_data, broadcast_addr)
    udp_socket.close()
if __name__ == '__main__':
    main()

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: