Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > WinAPI Socket, recv, узнать кол-во байт под буфер


Автор: ivsh 19.11.2013, 10:32
Приветствую, форумчане!
Пишу сетевое приложение. Возник вопрос с функцией recv, прием данных из сокета.
В ней нужно указывать буфер и его размер, а как мне узнать сколько выделить памяти под буфер?
Если я статически буду выделять 1кБ, а прийдут данные на 1МБ, то я не получу остальную часть.

Программа. Протокол TCP/IP. Сокет создаю в потоковом режиме, то есть
Код

mysocket = socket(AF_INET, SOCK_STREAM, 0)

Далее по коду, читаю данные
Код

dataReceivedTotal = recv(my_sock, dataReceived, 1024, 0)

где dataReceived - буфер, 1024 - размер буфера, а dataReceivedTotal - кол-во полученных байтов.
Дело в том, что я не знаю сколько байт пришло или как это определить, чтобы выделить соотв. по размеру буфер.
Функция recv возвращает кол-во принятых байт уже после записи в буфер.
Вот как определить какого размера выделить буфер под принимаемые данные?

И второй вопрос.
 Работаю с сокетом в цикле, отправляю данные клиенту, назовем ДАННЫЕ1 , при этом принимаю данные от клиента, если от клиента что-то пришло, то обрабатываю его запрос и отправляю ему РЕЗУЛЬТАТ1 + ДАННЫЕ1, иначе просто ДАННЫЕ1. 
 Примерно так:

Код

while (true)
{
    // Принимаю данне.
    dataReceivedTotal = recv(my_sock, dataReceived, 1024, 0);
    if (dataReceivedTotal > 0)
    {
        // Обработка данных пользователя.
    }
    else
    {
        // Отправляю стандартные данные.
    }
}


Выход из цикла должен осуществляться, если пользователь закрыл соединение.
 В документации написано:
Цитата

If the connection has been gracefully closed, the return value is zero.

Если соединение закрыто успешно, то получите 0.
 Собственно вопрос, как мне различать состояния, когда пользователь ничего не прислал и когда он закрыл соединение?

Автор: feodorv 19.11.2013, 19:53
Цитата(ivsh @  19.11.2013,  11:32 Найти цитируемый пост)
то я не получу остальную часть

Почему? Получите частями при следующих чтениях из сокета...

Цитата(ivsh @  19.11.2013,  11:32 Найти цитируемый пост)
Функция recv возвращает кол-во принятых байт уже после записи в буфер.

Если Вам интересно число доступных для чтения байт до recv, то можете воспользоваться вызовом ioctl( FIONREAD ), например, для виндов:
Код
  unsigned long v = 0;
  if( (rv = ioctlsocket( sock, FIONREAD, &v)) == SOCKET_ERROR ) /* error */



Цитата(ivsh @  19.11.2013,  11:32 Найти цитируемый пост)
Собственно вопрос, как мне различать состояния, когда пользователь ничего не прислал и когда он закрыл соединение? 

А у Вас сокет синхронный или ассинхронный? Если синхронный, то, простите, из recv Вы не вернётесь, пока удалённая сторона не пришлёт что-нибудь или не закроет сокет, вот так)))

Автор: ivsh 19.11.2013, 21:24
Цитата

А у Вас сокет синхронный или ассинхронный? Если синхронный, то, простите, из recv Вы не вернётесь, пока удалённая сторона не пришлёт что-нибудь или не закроет сокет, вот так)))

feodorv, да, сокет синхронный, в цикле что-то не заработало)
Да, я понял, что нужно асинхронно сделать. У меня суть задачи, помимо того, что я принимаю данные от пользователя, мне нужно ему отправлять другие данные, через один сокет.
Приложение работает как веб-сервер, принимает от браузера запрос на открытие веб-сокета, а затем шлет ему данные через него, и браузер также отправляет данные через этот же веб-сокет.
То есть открыли сокет, установили соединение, далее слушаю сокет, если есть запросы через него, то обрабатываю запрос и отсылаю результат, если нет, то шлю стандартные данные. Как мне реализовать это?

Автор: feodorv 20.11.2013, 23:02
Цитата(ivsh @  19.11.2013,  22:24 Найти цитируемый пост)
далее слушаю сокет, если есть запросы через него, то обрабатываю запрос и отсылаю результат, если нет, то шлю стандартные данные

Задача не понятна. если нет, то шлю стандартные данные - куда? кому? через прослушиваемый сокет???

Автор: ivsh 21.11.2013, 07:26
feodorv, уже разобрался. Ответ нашел в книге "Программирование на С++ глазами хакера". Пробую.

Автор: akizelokro 6.1.2014, 16:25
Некоторые люди "засаживают" recv в новый поток.
Есть ещё, кажисть, в WinSock такая фича как установка таймаута для сокета на чтение.

Долго праздновал, все "интересные" (где хоть что-то не совсем глупое могу написать) пропустил. Не дело это!  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)