powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Чтение из именнованного канала
25 сообщений из 31, страница 1 из 2
Чтение из именнованного канала
    #39701008
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть функция (для простоты восприятия сокращена обработка ошибок и чистка памяти),
которая вычитывает данные из named pipe канала.
Код: plaintext
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.
BOOL RecvData(LPBYTE* ppbRecvData, LPDWORD pdwRecvSize)
{
	LPBYTE ptrBlob = static_cast<LPBYTE>(::malloc(64UL * 1024UL));
	if (ptrBlob = NULL)
		return FALSE;

	DWORD	dwReadBytes	= 0UL;			// кол-во считанных байт за последнюю итерацию
	DWORD	dwTotalSize		= 0UL;		// общий размер считанных данных, байт
	DWORD	dwBufferSize	= 64UL * 1024UL;	// размер буфера для приема данных, байт
	LPBYTE	pbEntry		= ptrBlob;		// точка записи новых данных

	while (::ReadFile(m_hConnection, pbEntry, dwBufferSize, &dwReadBytes, NULL) == FALSE)
	{
		DWORD dwErrCode = ::GetLastError();
		if (dwErrCode != ERROR_MORE_DATA)
			return FALSE;

		dwTotalSize	 += dwReadBytes;
//		dwBufferSize *= 2UL;		// удвоенный размер

		pbEntry = static_cast<LPBYTE>(::malloc(dwTotalSize + dwBufferSize));
		if (pbEntry == nullptr)
			return FALSE;

		::CopyMemory(pbEntry, ptrBlob, dwTotalSize);
		::free(ptrBlob);
		
		ptrBlob = pbEntry;
		pbEntry	= ptrBlob + dwTotalSize;
	}
	
	*pdwRecvSize = dwTotalSize + dwReadBytes;
	*ppbRecvData = ptrBlob;

	return TRUE;
}


Не понимаю, почему ReadFile считает что вычитала все данные, если я увеличиваю размер буфера dwBufferSize в два раза после каждой неудачной итерации (см. закоментированную строку в коде - удвоенный размер)?

Например, если поступили 200 КБ данных, то ReadFile сначала вычитывает 64КБ и возвращает FALSE, потом я предоставляю ей удвоенный буфер в 128КБ. ReadFile вычитывает, скажем, еще 70КБ. ReadFile при этом возвращает TRUE, в dwReadBytes помещает размер считанных данных меньший, чем переданный ей буфер dwBufferSize. Если сложить все что я вычитал (64 + 70 < 200), то получится что dwTotalSize меньше, чем реально было данных, которые были помещенны в канал отправителем.

Существует два финта ушами, которые решают проблему:

1. перед началом чтения вызвать функцию PeekNamedPipe , узнать сколько данных, выделить нужный буфер сразу и считать все
2. закоментировать строку с удвоением буфера и читать данные только в буфер одинакового размера - 64КБ

Я бы всегда пользовался первым методом, т.к. не пришлось бы геморройничать с перевыделением буфера, копированием данных и прочим, но я пока не обкатал его и доверия он особо у меня не вызывает.
Второй метод меня не устраивает, т.к. при значительных объемах передаваемых данных (700 МБ и более), вычитывать их по 64КБ получается оччееееень дооооооолго.

Поэтому я и решил на каждую неудачную итерацию удваивать размер буфера, но столкнулся с тем, что система считает, что я все вычитал, хотя реально данных пришло больше, что и подтверждает PeekNamedPipe , если ее вызвать в самом начале.

Либо я чего-то не понимаю, либо к концу рабочего дня уже начинаю тупить и не вижу ошибку в своем коде.

Есть идеи, что это может быть ?

PS
именнованный канал создан с IO буфером в 64 КБ

сервер, перед закрытием канала вызывает FlushFileBuffers

клиент вычитывает данные после вызова TransactNamedPipe с переданными пустыми значениями параметров (для ускорения сетевого обмена, вместо WriteFile/ReadFile).
То есть функция ничего не вычитывает сама, только выполняет отправку данных (запрос) и организует прием (ответ) без считывания данных, дальше работает моя RecvData.

Я знаю что в MSDN сказано что TransactNamedPipe не гарантирует доставку данных свыше 64КБ, тогда почему стабильно работают два других метода ?


--------------------------------------------------------------
o(O_O)o
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701011
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Второй метод - единственно работающий. И не беспокойся, дольше он не будет. Не надо
использовать MESSAGE режим.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701013
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum,

почему по вашему она не может заполнить то что ей предоставили? наверное надо проверять сколько прочиталось pNumberOfBytesRead...


автор2. закоментировать строку с удвоением буфера и читать данные только в буфер одинакового размера - 64КБ
OVERLAPPED и два буфера - пока один обрабатывается, в другой читается.
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701014
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovВторой метод - единственно работающий. И не беспокойся, дольше он не будет. Не надо
использовать MESSAGE режим.

Да я использую MESSAGE режим, т.к. он мне удобнее и лучше отражает логику работы службы.

Я бы не парился, если бы его (стабильный буфер) не попробовал, когда вычитываю данные, то он тупит очень :)
Речь не о миллисекундах, там уже на минуты счет идет в сети на 1Gbps сетевухах, даже если все в виртуалках на одном компе-гипервизоре.

Я пробовал пересылать около гигабайта данных в режиме с удваением буфера (оказалось что не все данные приходили :) ), но даже если я не досчитался нескольких десятков/сотен килобайт, такой подход работает быстрее....

Наверное придется тогда мучить первый способ, обложить его проверками и тестами
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701016
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)почему по вашему она не может заполнить то что ей предоставили?
понятия не имею, сеть стабильная 1Gbps :), комп уровня Core i7 6700K c 32 GB RAM на борту

kealon(Ruslan)наверное надо проверять сколько прочиталось pNumberOfBytesRead...
именно так я и нашел этот косяк.

отправленный пакет находится в сжатом виде, когда его считал, то расжать не смог из-за ошибки расжимальщика, начал выяснять и обнаружил что получаю не все данные
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701017
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)OVERLAPPED и два буфера - пока один обрабатывается, в другой читается.
я не думаю, что здесь проблема производительности, т.к. в тестовой среде у меня пока один клиент - один сервер - один запрос, плюс PeekNamedPipe говорит видит все пришедшие данные в полном объеме - это 100% проверено и перепроверено
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701023
Котовасия
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum,

покажи, как канал создаешь.
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701031
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Котовасияпокажи, как канал создаешь.
если сильно упростить, то клиент коннектится примерно так (или вы про серверную часть ?)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
HANDLE ptrLink = ::CreateFile(ptrPipeName, GENERIC_READ|GENERIC_WRITE, 0UL, NULL, OPEN_EXISTING, 0UL, NULL);
if (ptrLink != INVALID_HANDLE_VALUE)
{
	DWORD dwMode = PIPE_READMODE_MESSAGE;
	if (::SetNamedPipeHandleState(ptrLink, &dwMode, NULL, NULL))
		return TRUE;
}



PS.
финт номер 1 рассыпался на тесте, тоже вычеркиваем
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701036
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrumотправленный пакет находится в сжатом виде, когда его считал, то расжать не смог из-за
ошибки расжимальщика, начал выяснять и обнаружил что получаю не все данные

Именно поэтому не надо использовать MESSAGE. Этот режим изначально сделан для сообщений
размером в считанные байты.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701040
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovCerebrumотправленный пакет находится в сжатом виде, когда его считал, то расжать не смог из-за
ошибки расжимальщика, начал выяснять и обнаружил что получаю не все данные

Именно поэтому не надо использовать MESSAGE. Этот режим изначально сделан для сообщений
размером в считанные байты.
склонен прислушаться к вашему мнению, буду пробовать
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701044
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrumбуду пробовать

В ходе этого процесса попробуй поразмыслить на фактом, что именованные трубки являются
одним из основных транспортов MS SQL. И лично я не слышал жалоб, чтобы до сервера не всё
доходило.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701058
Котовасия
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum, а при создании канала /*см. CreateNamedPipe()*/- указал режим PIPE_TYPE_MESSAGE?
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701081
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КотовасияCerebrum, а при создании канала /*см. CreateNamedPipe()*/- указал режим PIPE_TYPE_MESSAGE?
Код: plaintext
1.
::CreateNamedPipe(lpPipeName, PIPE_ACCESS_DUPLEX, (PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT|PIPE_ACCEPT_REMOTE_CLIENTS), PIPE_UNLIMITED_INSTANCES, (64UL * 1024UL), (64UL * 1024UL), 250UL, lpSA);
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701176
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
malloc() разве не пережиток C ?
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701181
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудухmalloc() разве не пережиток C ?malloc() это функция менеджера памяти использующегося в С.
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701197
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owlполудухmalloc() разве не пережиток C ?malloc() это функция менеджера памяти использующегося в С.
ну. в C++ то она зачем, там есть new & co?
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701383
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудухв C++ то она зачем, там есть new & co?

Когда new сумеет выделять что-то сложнее массива одинаковых структур, тогда о нём можно
будет говорить серьёзно. До тех пор std::malloc() - наше всё.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701716
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудухWhite Owlпропущено...
malloc() это функция менеджера памяти использующегося в С.
ну. в C++ то она зачем, там есть new & co?ахах, а ты думаешь new святым духом пользуется для выделения памяти =)
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39701751
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemarglполудухпропущено...

ну. в C++ то она зачем, там есть new & co?ахах, а ты думаешь new святым духом пользуется для выделения памяти =)
Код: plaintext
1.
2.
3.
4.
int *ptr = new int;
// оператор new выделяет память и конструирует объект по месту. Память выделяет так:
int *ptr = (int*) malloc(4) // malloc() эквивалент new
free(ptr) // освободить память



на какой-то конфе кто-то ляпнул, что в C++ есть new и теперь можно malloc() не трогать
сам то я джун ещё в сях, вникаю
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39702382
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а, этот "кто-то" это Страуструп... ляпнул .
авторОтказаться от использования malloc() в пользу оператора new, от realloc() — в пользу типа vector. Более безопасным будет использование умных указателей, таких как shared_ptr и unique_ptr, доступных с одиннадцатой версии стандарта.
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39702488
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
полудух,

ляпнул то он ляпнул, вот только чуть что серьёзное и все эти мальчики-побегайчики разбегаются и приходит жёсткий си

хотя если воспринимать этот как совет для ограниченных, то да, дельный
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39702852
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все он правильно сказал. Надо пользоваться более высокоуровневым new.

А то что внутре у ней malloc, это можно и не знать
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39702855
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
malloc() + memset()

или

malloc() + WTF!
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39705276
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Чтение из именнованного канала
    #39711877
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Переписал все с MESSAGE_TYPE на BYTE_TYPE. Теперь сервер создается как PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT|PIPE_ACCEPT_REMOTE_CLIENTS, а толку - ни фига!

Как клиент недогружал так и недогружает данные, пока принудительно не скажешь, что буфер не более 64К.

На серверной стороне WriteFile сообщает, что все отправлено столько сколько просили.
Кроме того, пробовал у WriteFile бить поток на блоки по 64К - не помогло. Сервер и в этом случае отрабатывает ок.
Клиент же (ReadFile) глотает начало блока с заголовком, потом еще 64КБ, потом как получится и сообщает: 0x000000E9 - No process is on the other end of the pipe... хотя процесс висит и пашет.

SetNamedPipeHandleState говорит, что клиент работает в режиме PIPE_TYPE_BYTE и ошибки здесь в выборе режима нет.

Думал может где все-таки косяк и я не вижу и где-то все же закрываю серверный канал раньше времени (вроде как FlushFileBuffers не должна этого позволять).
Специально закоментил код, который вызывает DisconnectNamedPipe и CloseHandle, оставил только FlushFileBuffers - клиент тупо завис на ReadFile и больше ничего не вычитывает.

Короче, в жопу!
Будет работать с 64К - пусть работает с 64К!

Всем отметившимся - спасибо
...
Рейтинг: 0 / 0
25 сообщений из 31, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Чтение из именнованного канала
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]