Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / recv выход из цикла / 25 сообщений из 178, страница 1 из 8
28.09.2018, 09:51
    #39709671
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
есть проблема чтения данных из сокета, а именно - протокол TCP/IP передает поток байтов от сервера к клиенту пакетами.
Размер пакетов имеет разную длину, которые помещаются в буфер, из которого функция recv и считывает данные

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

Пример кода:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
	while (res>0)
	{	
	res = recv(sock, rbuff, sizeof(rbuff), 0);    

	tmp = cp1251toUtf8(rbuff,res);

	}



Цикл выбирает все данные из буфера и останавливается в режиме ожидания на строке

Код: plaintext
1.
	res = recv(sock, rbuff, sizeof(rbuff), 0);    



Какие есть варианты выхода из цикла?
...
Рейтинг: 0 / 0
28.09.2018, 09:59
    #39709675
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Одно из двух:
1. Ты должен знать заранее сколько байт надо прочитать, т.е. перед данными передается их размер.
2. Есть какой-то маркер конца данных. Т.е. надо проверять что в принятом есть этот маркер.

Обычно делают по первому варианту.
...
Рейтинг: 0 / 0
28.09.2018, 10:11
    #39709683
Cerebrum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rb,

почитай про setsockopt и опцию SO_RCVTIMEO
...
Рейтинг: 0 / 0
28.09.2018, 10:18
    #39709685
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dima TОдно из двух:
1. Ты должен знать заранее сколько байт надо прочитать, т.е. перед данными передается их размер.
2. Есть какой-то маркер конца данных. Т.е. надо проверять что в принятом есть этот маркер.

Обычно делают по первому варианту.

Первый вариант не подходит, а второй можно попробовать
...
Рейтинг: 0 / 0
28.09.2018, 11:13
    #39709721
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rb,

Делаешь сокет O_NONBLOCK и читаешь в цикле пока recv не вернёт ошибку EWOULDBLOCK
...
Рейтинг: 0 / 0
28.09.2018, 11:37
    #39709736
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbесть проблема чтения данных из сокета, а именно - протокол TCP/IP передает поток байтов от сервера к клиенту пакетами.


Нет, ты ошибаешься, передача TCP идёт потоком. Пакетов никаких нет.


авторРазмер пакетов имеет разную длину, которые помещаются в буфер, из которого функция recv и считывает данные

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

Пример кода:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
	while (res>0)
	{	
	res = recv(sock, rbuff, sizeof(rbuff), 0);    

	tmp = cp1251toUtf8(rbuff,res);

	}



Цикл выбирает все данные из буфера и останавливается в режиме ожидания на строке

Код: plaintext
1.
	res = recv(sock, rbuff, sizeof(rbuff), 0);    



Какие есть варианты выхода из цикла?

recv возвращает отрицательное число при закрытии сокета и прочих проблемах.
Вот это и надо проверять.
Всё это есть в документации.
...
Рейтинг: 0 / 0
28.09.2018, 11:38
    #39709740
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
1. Ты должен знать заранее сколько байт надо прочитать, т.е. перед данными передается их размер.

Это не обязательно.
...
Рейтинг: 0 / 0
28.09.2018, 11:46
    #39709749
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbпротокол TCP/IP передает поток байтов от сервера к клиенту пакетами.

"Неправильно ты, дядя Фёдор, бутерброд ешь."
Надо говорить так: "протокол TCP/IP передает поток байтов". Точка. Никакого разделения на
"пакеты", видимые прикладному уровню, в нём нет.

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

Это не проблема. Проблема в том, что ты принятые байты не обрабатываешь сразу по принятии.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 12:36
    #39709774
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
MasterZivSergey_rbесть проблема чтения данных из сокета, а именно - протокол TCP/IP передает поток байтов от сервера к клиенту пакетами.


Нет, ты ошибаешься, передача TCP идёт потоком. Пакетов никаких нет.


авторРазмер пакетов имеет разную длину, которые помещаются в буфер, из которого функция recv и считывает данные

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

Пример кода:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
	while (res>0)
	{	
	res = recv(sock, rbuff, sizeof(rbuff), 0);    

	tmp = cp1251toUtf8(rbuff,res);

	}



Цикл выбирает все данные из буфера и останавливается в режиме ожидания на строке

Код: plaintext
1.
	res = recv(sock, rbuff, sizeof(rbuff), 0);    



Какие есть варианты выхода из цикла?

recv возвращает отрицательное число при закрытии сокета и прочих проблемах.
Вот это и надо проверять.
Всё это есть в документации.

Сокет не закрывается после получения данных
...
Рейтинг: 0 / 0
28.09.2018, 12:40
    #39709779
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbDima TОдно из двух:
1. Ты должен знать заранее сколько байт надо прочитать, т.е. перед данными передается их размер.
2. Есть какой-то маркер конца данных. Т.е. надо проверять что в принятом есть этот маркер.

Обычно делают по первому варианту.

Первый вариант не подходит, а второй можно попробовать

Второй вариант не прокатил, т.к. в потоке есть символы перевода строки
...
Рейтинг: 0 / 0
28.09.2018, 12:40
    #39709780
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbСокет не закрывается после получения данных

Поэтому-то твой цикл и не завершается. Обрабатывая данные внутри него.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 12:59
    #39709800
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovSergey_rbСокет не закрывается после получения данных

Поэтому-то твой цикл и не завершается. Обрабатывая данные внутри него.


Не закрывается, потому что так устроен обмен.

Увеличил размер буфера, чтобы в него гарантированно помещался весь объем принятых данных,
Каждый раз размер данных получается разный. потому что передача идет пакетами, причем размер пакетов произвольный, поэтому считывать надо в цикле.
...
Рейтинг: 0 / 0
28.09.2018, 13:12
    #39709812
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbКаждый раз размер данных получается разный. потому что передача идет пакетами, причем
размер пакетов произвольный, поэтому считывать надо в цикле.

Ты ещё не знаешь, что пакеты могут как делиться на части, так и склеиваться в один.
Повторяю медленно: обрабатывай каждую принятую порцию данных внутри своего цикла.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 13:40
    #39709831
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovSergey_rbКаждый раз размер данных получается разный. потому что передача идет пакетами, причем
размер пакетов произвольный, поэтому считывать надо в цикле.

Ты ещё не знаешь, что пакеты могут как делиться на части, так и склеиваться в один.
Повторяю медленно: обрабатывай каждую принятую порцию данных внутри своего цикла.


Я их обрабатываю
Мне надо знать, когда функция recv считала последний пакет.

проверка на количество считанных байтов не подходит, т.к. оно больше 0
Проверка на наличие символа \n тоже не прокатывает, т.к. в пакете есть символы перевода строки.
...
Рейтинг: 0 / 0
28.09.2018, 13:45
    #39709833
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
В INDY сначала считывается количество полученных строк, затем считываются строки.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TIdTCPConnection.ReadStrings(var AValue: TStrings; AReadLinesCount: Integer = -1);
Var
  i: Integer;
begin
  if AReadLinesCount <= 0 then begin
    AReadLinesCount := ReadInteger;
  end;
  for i := 0 to AReadLinesCount - 1 do begin
    AValue.Add(ReadLn);
  end;
end;
...
Рейтинг: 0 / 0
28.09.2018, 14:09
    #39709849
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbМне надо знать, когда функция recv считала последний пакет.

Не существует в природе никакого "последнего пакета". За исключением того, после которого
соединение закрывается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 14:11
    #39709851
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbВ INDY сначала считывается количество полученных строк

Значит инди сначала передаёт количество передаваемых строк. О чём тебе и говорили:
передавай длину данных перед самими данными.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 14:19
    #39709855
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovSergey_rbМне надо знать, когда функция recv считала последний пакет.

Не существует в природе никакого "последнего пакета". За исключением того, после которого
соединение закрывается.


да не закрывается соединение.
...
Рейтинг: 0 / 0
28.09.2018, 14:29
    #39709865
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovSergey_rbВ INDY сначала считывается количество полученных строк

Значит инди сначала передаёт количество передаваемых строк. О чём тебе и говорили:
передавай длину данных перед самими данными.


Не могу я менять алгоритм работы сервера, т.к. на нем крутятся терминалы
...
Рейтинг: 0 / 0
28.09.2018, 16:19
    #39709970
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Ну тогда ничего не поделаешь, придётся применять мозг или нанимать программиста.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 16:24
    #39709975
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovНу тогда ничего не поделаешь, придётся применять мозг или нанимать программиста.


Так где же взять этого программиста?
...
Рейтинг: 0 / 0
28.09.2018, 16:56
    #39710008
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Локализовал проблему - при получении 2-х пакетов, теряется первый пакет, т.е. функция выдает к-то байт, но сам буфер пустой.
Поставил
Код: plaintext
1.
Sleep(100)



Не помогло.

Есть подозрение, что буфере остается мусор от предыдущих запросов
...
Рейтинг: 0 / 0
28.09.2018, 17:42
    #39710042
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbпри получении 2-х пакетов, теряется первый пакет, т.е. функция выдает к-то байт, но сам
буфер пустой.

Что логично, поскольку ты и принимаешь в один буфер и складываешь в одно место, так что
каждый следующий принятый кусок затирает предыдущий. Включи уже голову.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
28.09.2018, 18:00
    #39710060
Sergey_rb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Dimitry SibiryakovSergey_rbпри получении 2-х пакетов, теряется первый пакет, т.е. функция выдает к-то байт, но сам
буфер пустой.

Что логично, поскольку ты и принимаешь в один буфер и складываешь в одно место, так что
каждый следующий принятый кусок затирает предыдущий. Включи уже голову.


если речь идет о этой строке,

авторtmp = cp1251toUtf8(rbuff,res);


То я выложил не всю обработку
Код: plaintext
1.
2.
			tmp = cp1251toUtf8(rbuff,res);
			line.append(tmp);




Первый пакет теряется даже в случает двух вызовов recv

Код: 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.
		res_total=recv(sock, rbuff, sizeof(rbuff), 0);

		wsprintf(t2, L" res_total = %d", res_total);

		::MessageBoxW(NULL,t2, L"GetStrings", MB_ICONEXCLAMATION | MB_OK);

		i=strlen(rbuff);
		wsprintf(t2, L" strlen = %d", i);

		::MessageBoxW(NULL,t2, L"Buf len", MB_ICONEXCLAMATION | MB_OK);

		tmp = cp1251toUtf8(rbuff,sizeof(rbuff));
		::MessageBoxW(NULL,tmp.c_str(), L"GetStrings total result", MB_ICONEXCLAMATION | MB_OK);

		 res = recv(sock, rbuff, sizeof(rbuff), 0);

		i=strlen(rbuff);
		wsprintf(t2, L" strlen = %d", i);

		::MessageBoxW(NULL,t2, L"GetStrings", MB_ICONEXCLAMATION | MB_OK);


		tmp = cp1251toUtf8(rbuff,sizeof(rbuff));

//		wstr = cp1251toUtf8((const char *)  rbuff, res); 		

		::MessageBoxW(NULL,tmp.c_str(), L"GetStrings result", MB_ICONEXCLAMATION | MB_OK);

		line.append(tmp);
...
Рейтинг: 0 / 0
28.09.2018, 18:16
    #39710076
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
recv выход из цикла
Sergey_rbПервый пакет теряется даже в случает двух вызовов recv

Это очередной псевдокод или этот бред реально написан в программе? Он в принципе не
работоспособен от "strlen()" и ниже.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / recv выход из цикла / 25 сообщений из 178, страница 1 из 8
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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