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

Передача данных по сети при помощи TcpClient

29.07.2023, 18:34. Показов 1335. Ответов 0

Студворк — интернет-сервис помощи студентам
Коллеги, приветствую!
Я создал приложения на основе клиент-сервер, которые обмениваются между собой данными, и файлами.
Соединение работает на основе класса :
Code
1
System::Net::Sockets::TcpClient^ Client
Я не знаю, может я вообще пошёл не по тому пути, но алгоритм действий такой:
1. На сервере запущена прослушка входящих соединений и соединение при запросе:
C++
1
2
3
4
5
6
System::Net::Sockets::TcpListener^ ServerListen;
System::Net::Sockets::TcpClient^ inClient;
 
if( ServerListen->Pending() ){
       inClient = ServerListen->AcceptTcpClient(); // подключаемся к клиенту
}
При соединении, формируются два канала для передачи данных:
C++
1
2
3
4
5
6
System::IO::StreamReader^ streamIn;
System::IO::StreamWriter^ streamOut;
 
streamIn = gcnew System::IO::StreamReader( dat->Client->GetStream() );  // получаем входящий поток
streamOut = gcnew System::IO::StreamWriter( dat->Client->GetStream( ) );
streamOut->AutoFlush = true;
2. В клиенте в общем всё похоже, только вначале клинет не ждёт, а посылает запрос на соединение. После чего тоже получаем потоки для передачи и приёма данных.
3. Далее передача числа от клиента к серверу посредством такого кода:
C++
1
2
3
4
5
6
7
8
9
static inline void Transfer(System::IO::StreamWriter^stream, System::UInt32 val)
{
    array<unsigned char>^ ubyte_Data = System::BitConverter::GetBytes( val );// переводим в строку байтов
    wchar_t leng = ubyte_Data->Length;//длина строки
    array<wchar_t>^ data = converArray_Char_to_Wchar( ubyte_Data );// конвертируем в массив wchar_t
 
    stream->Write( leng ); // передаём длину строки - 1 символ
    stream->Write( data ); // передаём строку - массив символов
}
На сервере принимаем число так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static inline System::UInt32 Ressive_UInt32(System::IO::StreamReader^stream )
{
    try{
    wchar_t leng = stream->Read(); // получаем длину строки в одном символе
    array<wchar_t>^ data = gcnew array<wchar_t>(leng); // подготавливаем массив
    stream->Read( data, 0, leng ); // ситаем строку
    array<unsigned char>^ bufferChar = ConverArray_WChar_to_char( data ); // преобразовываем строку
 
    return System::BitConverter::ToUInt32(bufferChar,0); // получаем из строки - число - выход из процедуры
 
    }catch (System::IO::IOException^ ){
        //System::Windows::Forms::MessageBox::Show(L"ошибка связи - клиент отключился");
    }
 
    return 0;
}//void
- По такому принципу ц меня реализована передача данных различных типов, но случаются очень редко - но сбои. На столько редко - что в режиме отладки я этот сбой ни разу не видел. Сбоят уже Релиз-сборки
- Но еще одна причина вопроса- что такая схема передачи данных очень медленная. Для передачи десятка цифр то неважно, но при передачи файлов, допустим в 50мегобайт, это превращается в боль ожидания.
При передачи файла я разбиваю его на блоки и пересылаю. Вот код:
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
System::IO::FileStream^ fs = gcnew  System::IO::FileStream( path,System::IO::FileMode::Open, System::IO::FileAccess::Read );
long long size = fs->Length;
 
unsigned int blockSize = 1024;
array<unsigned char>^ bufferChardata = gcnew array<unsigned char>( blockSize );
 
Transfer( streamOut, (unsigned int)size );
Transfer( streamOut, (unsigned int)blockSize );
 
long long bufPos = 0;
long long lengLimit = size - blockSize;
System::IO::BinaryReader^ breader = gcnew System::IO::BinaryReader(fs);
 
bool goRead = true;
bool rez = true;
 
        while(goRead)
        {
            if(bufPos<lengLimit)// передача целых строк
            {
                bufferChardata = breader->ReadBytes( blockSize );//прочитали из файла
                Transfer( streamOut, (unsigned int)blockSize ); // передали длину
                Transfer( streamOut, bufferChardata ); // передали данные
 
            }else{ // передача последней остаточной строки
                unsigned int finalLeng = size - bufPos;
                bufferChardata = breader->ReadBytes( finalLeng );
                Transfer( streamOut, (unsigned int)finalLeng ); // передали длину
                Transfer( streamOut, bufferChardata ); // передали данные
                goRead = false;
            }
            bufPos = bufPos + blockSize;
 
        }///while
- при приёме происходит похожая ситуация. Не буду приводить код. Суть в том, что всё так прекрасно работает но жутко медленно. Локика подсказывает, что если передавать строки большими длинами - то это ускорит ситуацию. И правда, если в коде размер буфера изменить с 1024 на 4096 - то процесс заметно ускоряется, но!...
-когда это проделываешь в тестовом режиме на одном компе
C++
1
cetAddr = System::Net::IPAddress::Parse(L"127.0.0.1")
- То всё работает норм.
Но при соединении с удалённым сервером, так можно передать только небольшие файлы в несколько килобайт. Файлы в пол-мегабайта уже не факт что передадутся нормально, а при больших размерах - гарантированный сбой.
При попытке поиска ошибки я выяснил, что при передачи строк, в какой то момент происходит какая то потеря, или рассинхрон в получении этих данных. т.е. отправитель всё отправляет и успешно рапортует об этом, вот получателю чтото не доходит, но как и почему это получается?
Я стал комать дальше, и в справке вычитал странный момент для функции приёма данных ReadBlock:
C++
1
2
3
System::IO::StreamReader^stream
.....
stream->ReadBlock( data, 0, leng );
В справке написано, что эта функция возвращает число считанных байт, и это может что число от 0 до заданного в leng
я честно говоря в ступоре, потому что в этой же справке написано, что это блокирующая функция, т.е. она обязательно считает указанную длину, если только не поток не оборвётся.
Я правильно понимаю, что она обязательно ждёт данные в буфере, до нужной длины, и только потом считывает нужную строку? или всё таки я ошибаюсь?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.07.2023, 18:34
Ответы с готовыми решениями:

Передача данных при помощи pipe
Смысл в том, что можно создать одно приложение (соответственно, один проект). При первом запуске приложение будет играть роль сервера, при...

Не работает передача данных с одного компьютера на другой при помощи sendto и recvfrom
Я пытаюсь передать данные с одного компа на другой при помощи связки sendto и recvfrom. Сообщение вроде бы отсылается без проблем, но...

Прекращается приём и передача данных через модем Yota при включении локальной сети
Друзья, здравствуйте. Напишу, как понимаю. Есть модем Zyxel keenetic omni II, в него включен модем Yota (LU150). Если модем включен в...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.07.2023, 18:34
Помогаю со студенческими работами здесь

TcpClient-TcpServer приложение. при передаче данных теряются байты
Здравствуйте всем! Пробую писать клиент-серверное приложение. Выбрал протокол TCP. Нашёл с учебника, как мне казалось, добрый пример, от...

Как считать данные из сети при помощи c#?
Люди! Помогите! В моей дипломной работе необходимо считать данные, которые приходят из сети на определенный IP и порт. как реализовать? вот...

Передача файлов при помощи компонентов ServerSocket и ClientSpcket
Здравствуйте, можете скинуть исходники или точные примеры как передавать файлы при помощи компонентов ServerSocket &amp; ClientSpcket! Да...

Создание локальной сети при помощи ADSL модема и свитча
Добрый день. У меня сложилась проблема. Есть ADSL модем (настройка bridge), свитч D-Link DES-1008D, 5 ПК (ПК1 - Win 7, остальные - Win XP...

При помощи алгоритмов кластеризации выявить нетипичное поведение пользователя в сети
Всем привет. Вопрос такой: есть набор данных, собранный из заголовков пакетов по сети. Надо при помощи алгоритмов кластеризации выявить...


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

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru