UDP w Pythonie

Unicast

Klient

# -*- coding: utf-8 -*-
import socket

UDP_IP = "192.168.1.70" #Oczywiście wybierzcie inny adres IP
UDP_PORT = 5005
MESSAGE = "Hello, World!"

print("UDP target IP:", UDP_IP)
print("UDP target port:", UDP_PORT)
print("message:", MESSAGE)

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
sock.settimeout(1)

try:
    response = sock.recv(1024)
    print(response)
except socket.timeout:
    print("No response")

Ważniejsze miejsca programu

Stworzenie gniazda. Wybieramy rodzinę AF_INET, oraz protokół SOCK_DATAGRAM, czylu UDP.

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP

Ustawienie czasu oczekiwania na odpowiedź, tutaj uwaga: w pytnonie tego typu interwały określa się jako zmienne float w sekundach — zatem 1 oznacza 1 sekundę a 1.5 półtorej.

sock.settimeout(1)

Serwer

# -*- coding: utf-8 -*-
import socket

UDP_IP = ""
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print("Otrzymalem:", data)
    sock.sendto("OK", addr)

Ważniejsze miejsca programu

Rozpoczęcie otrzymywania wiadomości z portu:

sock.bind((UDP_IP, UDP_PORT))

Odczytanie pakietu.

Note

By odpowiedzieć na pakiet UDP musimy znać adres z którego ów pakiet przyszedł, funkcja recvfrom zwraca dwie wartości — otrzymane dane oraz adres z których je otrzymano.

Składnia:

data, addr = sock.recvfrom(1024)

powoduje że pierwsza zwracana wartość trafia do zmiennej data a druga do addr.

Broadcast

Serwer

Serwer jest bez zmian.

Klient

Zmianie uległa jedna linijka kodu.

# -*- coding: utf-8 -*-
import socket

UDP_IP = "192.168.1.255"
UDP_PORT = 5005
MESSAGE = "Hello, World!"

print("UDP target IP:", UDP_IP)
print("UDP target port:", UDP_PORT)
print("message:", MESSAGE)

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP

sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

sock.settimeout(1)

try:
    response = sock.recv(1024)
    print(response)
except socket.timeout:
    print("No response")

Ważniejsze miejsca programu

Ustawienie że gniazdo służy do broadcastów:

sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

Multicast

Server

# -*- coding: utf-8 -*-
import socket
import struct
import sys

multicast_group = '224.3.29.71'
server_address = ('', 10000)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind(server_address)

group = socket.inet_aton(multicast_group)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    print('\nwaiting to receive message')
    data, address = sock.recvfrom(1024)

    print('received %s bytes from %s' % (len(data), address))
    print(data)

    print('sending acknowledgement to', address)
    sock.sendto('ack', address)

Ważniejsze miejsca w programie:

Konwersja ciągu znaków na adres IP

group = socket.inet_aton(multicast_group)

Stworzenie struktury danych odpowiedzialnych za ustawienie adresu:

mreq = struct.pack('4sL', group, socket.INADDR_ANY)

Wartością opcji IP_ADD_MEMBERSHIP jest struktura ip_mreq, tutaj pakujemy dwa obiekty pythona do takiego rozmiaru.

Klient

Klient po prostu wysyła wiadomość na adres grupy.