Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 01.06.2025
Сообщений: 4

Потери данных в локальной сети на протоколе UDP

01.06.2025, 17:14. Показов 4531. Ответов 6

Студворк — интернет-сервис помощи студентам
У меня есть простой клиент-сервер на языке C++, C# и на C++ с использованием фреймворка QT.
Я передаю видеофайл с клиента на сервер. Влияет ли язык программирования на потери? Странно звучит, но не знаю как правильно сформулировать. Но при передаче заметил, что потери разные. C++ передал все без потерь, а реализация на C# потеряла часть данных. С чем это может быть связано?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <windows.h>
#include <iostream>
#include <fstream>
#include <chrono>
#include <cstdint>
 
#pragma comment(lib, "Ws2_32.lib")
 
#define PORT 8080
#define BUFFER_SIZE 1400
 
int main() {
    WSADATA wsaData;
    SOCKET udpSocket;
    struct sockaddr_in serverAddr, clientAddr;
    char buffer[BUFFER_SIZE];
    int clientLen = sizeof(clientAddr);
    bool receivingStarted = false;
 
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed\n";
        return EXIT_FAILURE;
    }
 
    udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udpSocket == INVALID_SOCKET) {
        std::cerr << "Socket creation failed: " << WSAGetLastError() << "\n";
        WSACleanup();
        return EXIT_FAILURE;
    }
 
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);
 
    if (bind(udpSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        std::cerr << "Bind failed: " << WSAGetLastError() << "\n";
        closesocket(udpSocket);
        WSACleanup();
        return EXIT_FAILURE;
    }
 
    std::ofstream outputFile("D:\\Video.copy(UDP).MKV", std::ios::binary);
    if (!outputFile) {
        std::cerr << "Failed to open file for writing.\n";
        closesocket(udpSocket);
        WSACleanup();
        return EXIT_FAILURE;
    }
 
    std::cout << "Waiting for UDP file data on port " << PORT << "...\n";
 
    uint64_t totalBytes = 0;
    std::chrono::high_resolution_clock::time_point start, end;
 
    DWORD timeout = 4000; 
    setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
 
    while (true) {
        int bytesReceived = recvfrom(udpSocket, buffer, BUFFER_SIZE, 0, (sockaddr*)&clientAddr, &clientLen);
        if (bytesReceived == SOCKET_ERROR) {
            int err = WSAGetLastError();
            if (err == WSAETIMEDOUT) {
                std::cout << "Receive timed out — assuming end of file.\n";
                break;
            }
            else {
                std::cerr << "recvfrom failed: " << err << "\n";
                break;
            }
        }
 
        if (!receivingStarted) {
            receivingStarted = true;
            start = std::chrono::high_resolution_clock::now();
        }
 
        outputFile.write(buffer, bytesReceived);
        totalBytes += bytesReceived;
    }
 
    if (receivingStarted) {
        end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> duration = end - start;
        double speed = static_cast<double>(totalBytes) / duration.count() / 1024;
 
        std::cout << "Received " << totalBytes << " bytes in " << duration.count() << " seconds.\n";
        std::cout << "Average speed: " << speed << " KB/s\n";
    }
    else {
        std::cout << "No data received.\n";
    }
 
    outputFile.close();
    closesocket(udpSocket);
    WSACleanup();
    return 0;
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
 
class UdpFileReceiver
{
    private const int Port = 8080;
    private const int BufferSize = 1400;
    private const int ReceiveTimeout = 3000; 
 
    static void Main()
    {
        try
        {
            using (UdpClient udpServer = new UdpClient(Port))
            {
                udpServer.Client.ReceiveTimeout = ReceiveTimeout;
                IPEndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
 
                string filePath = @"D:\Video.copy(UDP#).MKV";
                using (FileStream outputFile = File.Create(filePath))
                {
                    Console.WriteLine($"Waiting for UDP file data on port {Port}...");
 
                    byte[] buffer = new byte[BufferSize];
                    long totalBytes = 0;
                    bool receivingStarted = false;
                    Stopwatch stopwatch = null;
 
                    try
                    {
                        while (true)
                        {
                            byte[] receivedData = udpServer.Receive(ref clientEndPoint);
 
                            if (!receivingStarted)
                            {
                                receivingStarted = true;
                                stopwatch = Stopwatch.StartNew();
                                Console.WriteLine("File transfer started...");
                            }
 
                            outputFile.Write(receivedData, 0, receivedData.Length);
                            totalBytes += receivedData.Length;
                        }
                    }
                    catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
                    {
                        Console.WriteLine("Receive timeout - assuming end of file.");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error receiving data: {ex.Message}");
                    }
 
                    if (receivingStarted && stopwatch != null)
                    {
                        stopwatch.Stop();
                        double duration = stopwatch.Elapsed.TotalSeconds;
                        double speed = totalBytes / duration / 1024; 
 
                        Console.WriteLine($"Received {totalBytes} bytes in {duration:F2} seconds.");
                        Console.WriteLine($"Average speed: {speed:F2} KB/s");
                    }
                    else
                    {
                        Console.WriteLine("No data received.");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Server error: {ex.Message}");
        }
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.06.2025, 17:14
Ответы с готовыми решениями:

Qt. как в протоколе UDP работать с несколькими сокетами?
Доброго времени суток! Есть приложение, которое постоянно принимает данные и может работать на...

Потери UDP пакетов
Всем здравствуйте...Столкнулся со следующей проблемой. Попытался передать довольно большой файл по...

Разработать библиотеку процедур для приёма-передачи данных по сети на основе протокола UDP
Здравствуйте. Вот задание. Разработать библиотеку процедур для приёма-передачи данных по сети на...

6
 Аватар для abit
867 / 526 / 148
Регистрация: 03.02.2013
Сообщений: 1,845
01.06.2025, 17:58
Цитата Сообщение от ORGKot Посмотреть сообщение
У меня есть простой клиент-сервер на языке C++, C# и на C++ с использованием фреймворка QT.
х-на себе там винегрет)
предположу что твой код на C# создает новый массив при каждом вызове Receive(), это значит постоянные аллокации памяти под новые массив, нагрузку на gc, паузы на gc, во время которых теряются пакеты и, конечно, фрагментацию памяти в куче, мой совет пишите на Rust, чтобы потом не переписывать)
ну как временный костыль можно попробовать ReceiveFrom(), там фиксированный буфер
1
0 / 0 / 0
Регистрация: 01.06.2025
Сообщений: 4
01.06.2025, 18:02  [ТС]
abit, во время тестов видел, что C# больше нагружал процессор и в целом потреблял больше всех ресурсов. Насчет винегрета, то это для вуза задание такое. Я сравниваю эти три реализации и должен сделать на основе тестов рекомендации.
0
 Аватар для abit
867 / 526 / 148
Регистрация: 03.02.2013
Сообщений: 1,845
01.06.2025, 18:06
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
    socket.Bind(new IPEndPoint(IPAddress.Any, Port));
    socket.ReceiveBufferSize = 65536;
    socket.ReceiveTimeout = 4000;
 
    byte[] fixedBuffer = new byte[BufferSize]; 
    EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
    
    while (true)
    {
        int bytesRead = socket.ReceiveFrom(fixedBuffer, ref remoteEP);
        outputFile.Write(fixedBuffer, 0, bytesRead);
    }
}
Добавлено через 4 минуты
Цитата Сообщение от ORGKot Посмотреть сообщение
сделать на основе тестов рекомендации
рекомендую Rust
1
0 / 0 / 0
Регистрация: 01.06.2025
Сообщений: 4
01.06.2025, 18:08  [ТС]
Хах, это конечно хорошо, но такие уж у меня исходные данные
0
9 / 7 / 2
Регистрация: 22.12.2024
Сообщений: 31
01.06.2025, 19:37
udp НЕ гаратирует доставку сообщений. Практически, это значит, что о потере сообщений, вам не сообщат (в отличие от TCP). Это значит, что это либо приемлемая ситуация, либо что сами должны проверять доставку (например, нумеровать пакеты, перезапрашивать, если потеряли и т.п.).

То, что C# не работает, а С++ работает, скорее случайность чем правило. В общем случае клиент может наливать вам больше трафика, чем вся принимающая цепочка способна пропустить. Например, роутер, или wifi или ещё кто может терять пакеты.
0
 Аватар для abit
867 / 526 / 148
Регистрация: 03.02.2013
Сообщений: 1,845
01.06.2025, 20:01
Цитата Сообщение от basiliscos Посмотреть сообщение
То, что C# не работает, а С++ работает, скорее случайность чем правило
по факту это будет правило, потому что C++ чаще успеет принять, чем C# пока возиться с gc
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.06.2025, 20:01
Помогаю со студенческими работами здесь

Передача с микрофона в udp и прием из udp на динамик
Собственно каким образом осуществить передачу данных с микрофона в сеть и прием из сети данных...

Утилита для получения статической информации по протоколам UDP, TCP, ICMP, IP.
Т. е. надо вывести статическую инфу аналогочную, получаемую при вызове netstat -s в cmd... Может...

Отправка текста по протоколу udp
Добрый день All Захотел поглубже изучить builder c++,и столкнулся с тем что не понимаю как...

Сервер получает файлы от клиента, склеивает все полученные файлы в один большой. Протокол взаимодействия UDP
Дали задание, надеюсь на вашу помощь или быть может есть какие-то исходники, буду рад любой помощи....

UDP протокол Важно!
Ребят в продолжении темы сокетов, работаю уже с UDP прооколом и возникла такая проблема: как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru