UDP

Материал из Xgu.ru

Перейти к: навигация, поиск
stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.

Если вы считаете, что её стоило бы доработать как можно быстрее, пожалуйста, скажите об этом.


UDP (User Datagram Protocol) — один из важнейших протоколов стека TCP/IP. В соответствии с 7-уровневой моделью OSI работает на четвёртом, транспортном уровне.

Содержание

[править] Потеря UDP-пакетов

Есть несколько причин, почему UDP-пакеты могут не доходить до адресата. Кроме собственно потерь на нижележащем уровне (физическом, канальном или сетевом), они могут отбрасываться уже на собственно уровне UDP.

В Linux, если пакет видится tcpdump-ом, но не видится приложением, тому может быть несколько причин:

  1. Контрольная сумма UDP-пакета неверна;
  2. Пакет убирается фильтром пакетов netfilter;
  3. Пакет убирается фильтром rp_filter[1];
  4. Приложение не успевает справиться с потоком пакетов, входящий буфер переполняется.

Проверить контрольную сумму можно с помощью tcpdump:

$ sudo tcpdump -i eth0 -vvv -nn udp dst port 53
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:04:48.145904 IP (tos 0×0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 61)
10.0.0.2.56497 > 10.0.0.1.53: [bad udp cksum 0x8f54 -> 0xb8fc!] 30234+ AAAA? www.twitter.com. (33)
17:04:48.145925 IP (tos 0×0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 61)
10.0.0.2.56497 > 10.0.0.1.53: [bad udp cksum 0x224d -> 0x2604!] 30234+ AAAA? www.twitter.com. (33)

Чаще всего такая проблема возникает из-за TCO (TCP offloading). Выключить его и перепроверить можно так:

# ethtool -K eth0 tx off rx off

Подробно данная проблема описана здесь:

Ещё на эту тему:

Подробнее о том, как рассчитывается контрольная сумма в UDP-пакетах:

Игнорировать ошибки в контрольной сумме можно заставить битом SO_NO_CHECK сокета[2].


[править] Программирование UDP-сокетов

[править] Python

Клиент:

import socket

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

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

Сервер:

import socket

UDP_IP = "127.0.0.1"
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 "received message:", data


Подробнее:

Работа с широковещательными пакетами:

[править] Дополнительная информация

[править] Примечания

  1. http://lkml.iu.edu//hypermail/linux/kernel/0906.0/02042.html
  2. http://sply.livejournal.com/406733.html
Источник — «http://xgu.ru:81/wiki/UDP»