Есть ли какая-либо возможность обойти размер пакета, отправляемого в дейтаграмму? [Ошибка 10040]

#python #sockets #udp #game-development #imutils

#python #сокеты #udp #разработка игр #imutils

Вопрос:

Я пытаюсь создать приложение с использованием python для совместного просмотра фильмов, но я постоянно получаю ошибки с :

[Errno 10040] Сообщение, отправленное в сокет дейтаграммы, было больше, чем внутренний буфер сообщений или какой-либо другой сетевой лимит, или буфер, используемый для приема дейтаграммы, был меньше самой дейтаграммы

Server.py

 BUFFOR_SIZE_DATA = 65536

# SERVER SETTINGS
server_socket_main = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket_main.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFOR_SIZE_DATA)

print(Fore.RED   'UDP Server')
host_name = socket.gethostname()
print('HOST NAME:',host_name)
host_ip_adress = ''
print('HOST IP:',host_ip_adress)
host_port = 1337
socket_adress_main = (host_ip_adress, host_port)
print('PORT:',host_port)
server_socket_main.bind(socket_adress_main)
print(Fore.GREEN   'Server is listening > > >')
print(Fore.WHITE   ' ')
print(Fore.WHITE   'Connected devices: ')

# VIDEO U WANT TO WATCH TOGETHER
server_video_main = cv2.VideoCapture('movies/exmpl.mp4')

# MAIN LOOP
while True:
    msg, client_addres_obligatory = server_socket_main.recvfrom(BUFFOR_SIZE_DATA)
    print('Connected from ', client_addres_obligatory)
    WIDTH = 1024
    while(server_video_main.isOpened()):
        _,frame = server_video_main.read()
        frame = imutils.resize(frame, width=WIDTH)
        encoded, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
        message = base64.b64encode(buffer)
        server_socket_main.sendto(message, client_addres_obligatory)
        cv2.imshow('HOST | Currently hosting', frame)
        key = cv2.waitKey(1) amp; 0xFF
        if key == ord('c'):
            server_socket_main.close()
            break

 

Client.py

 client_socket_main.sendto(welcomemessage.encode(), (client_ip_adress, client_port))

while True:
    packet,_ = client_socket_main.recvfrom(BUFFOR_SIZE_DATA)
    data = base64.b85decode(packet,' /')
    npdata = np.fromstring(data, dtype=np.unit8)
    frame = cv2.imdecode(npdata, 1)
    cv2.imshow('Currently watching ', frame)
    key = cv2.waitKey(1) amp; 0xFF
    if key == ord('c'):
        client_socket_main.close()
        break

 
 data = base64.b85decode(packet,' /')
 

Ошибка типа: b85decode() принимает 1 позиционный аргумент, но было задано 2

Заранее спасибо!

Ответ №1:

Ограничение в 64 КБ определяется не UDP, а IP. Вот заголовок IPv4 из исходного RFC:

     0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |Version|  IHL  |Type of Service|          Total Length         |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |         Identification        |Flags|      Fragment Offset    |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |  Time to Live |    Protocol   |         Header Checksum       |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |                       Source Address                          |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |                    Destination Address                        |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   |                    Options                    |    Padding    |
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 

Видите это поле «Общая длина»? Это 16 бит, поэтому его максимальное значение равно 0xffff, что равно 64Ki. Это даже включает заголовки, поэтому фактический максимальный размер меньше.

Кроме того, типичный MTU в Интернете составляет 1500 байт, иногда меньше (опять же, включая заголовки). Отправка пакетов, превышающих MTU, — это путь к неприятностям, потому что это означает, что произойдет фрагментация IP, что нежелательно.

Вам нужно разбить данные на более мелкие фрагменты или использовать TCP, который позаботится об этом за вас.

Комментарии:

1. Это сообщение об ошибке очень четкое. base64.b85decode ожидает один аргумент, но вы дали ему два.