Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сокеты: виснет recv 
:(
    Опции темы
Alca
Дата 24.6.2009, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Работаю с POP3. Если получен весь ответ сервера (т.е. строка [server_answer\r\n]), то recv виснет, а потом отваливается по таймауту (:recv возвращяет 0). Можно как-то отловить конец ответки - "\r\n"?
Что здесь можно сделать? Желательно без BOOST.
Код

std::string sRecvBytes() {   
    std::string  sRes      = "";
  
    const size_t cuiInSize = 20;
    std::string  sIn(cuiInSize, '\0');

    for (;;) {   
        INT iRes = ::recv(&sIn[0], cuiInSize, 0);   //здесь виснет
        assert(iRes >= 0);
        if (0 == iRes) {
            break;
        }    

        sRes.append( std::string(sIn.begin(), sIn.begin() + iRes) );
    } 

    return sRes;    


Такая же проблема http://www.cyberforum.ru/visual-cpp/thread11542.html


--------------------
PM WWW ICQ Skype Jabber   Вверх
Lazin
Дата 24.6.2009, 05:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



оно не виснет, оно ждет, передающая сторона скорее всего передает меньше 20 байт
PM MAIL Skype GTalk   Вверх
Alca
Дата 24.6.2009, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Цитата

оно не виснет, оно ждет, передающая сторона скорее всего передает меньше 20 байт

Я согласен, так оно и есть. Мне надо, чтоб ::recv сразу вернула управление программы, а не ждало.


--------------------
PM WWW ICQ Skype Jabber   Вверх
azesmcar
Дата 24.6.2009, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



Цитата(Alca @  24.6.2009,  08:49 Найти цитируемый пост)
Я согласен, так оно и есть. Мне надо, чтоб ::recv сразу вернула управление программы, а не ждало. 

используй неблокирующий сокет.
Код

//ulong_t mode = 0; //blocking mode
ulong_t mode = 1; //non-blocking mode
ioctlsocket( socket, FIONBIO, &mode );

PM   Вверх
Alca
Дата 24.6.2009, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Типа так?
Код

std::string CXTcpClientSocket::sRecvBytes() {   
    std::string  sRes      = "";
    INT          iRes      = SOCKET_ERROR;   
    BOOL         bRes      = FALSE;   
    const size_t cuiInSize = 20;
    std::string  sIn(cuiInSize, '\0');
    
    //установка величины таймаута
    timeval      ReceiveTimeout = {0};
    ReceiveTimeout.tv_sec  = 2;
    ReceiveTimeout.tv_usec = SOCKET_TIMEOUT;              

    fd_set fds = {0};
    FD_ZERO(&fds);
    FD_SET(m_puiSocket, &fds);
    
    
    for (;;) {   
        //entering non blocking
        ULONG block = 1;
        iRes = ::ioctlsocket(m_puiSocket, FIONBIO, (ULONG FAR*) &block);
        assert(0 == iRes);
        
        iRes = ::select(0, &fds, NULL, NULL, &ReceiveTimeout);
        if (0 == iRes) {
            break;
        }
        
        iRes = ::recv(m_puiSocket, &sIn[0], cuiInSize, 0);  
        assert(iRes >= 0);
        if (0 == iRes) {
            break;
        }    

        sRes.append( std::string(sIn.begin(), sIn.begin() + iRes) );
    } 

    return sRes;    



Добавлено @ 09:49
Какой порядок вызовов:
Цитата

::ioctlsocket
::select
::rcv
 ???

Это сообщение отредактировал(а) Alca - 24.6.2009, 09:53


--------------------
PM WWW ICQ Skype Jabber   Вверх
azesmcar
Дата 24.6.2009, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



Alca

Установить можно 1 раз, после accept -а, он таким и останется.
PM   Вверх
Alca
Дата 24.6.2009, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Цитата

после accept -а

accept -а у меня нет.

Добавлено через 3 минуты и 20 секунд
::ioctlsocket после этого? после того как создал сокет?
Код

m_puiSocket = ::socket(iAf, iType, iProtocol);  
/*... ::ioctlsocket ... ???*/




--------------------
PM WWW ICQ Skype Jabber   Вверх
azesmcar
Дата 24.6.2009, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



Alca

не важно где, можно устанавливать 1 раз, после этого сокет станет неблокирующим.
PM   Вверх
GrayCardinal
Дата 24.6.2009, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 3
Всего: 58



Код

__export int DIONREAD (int fd)
{
    int ret = -1;
    if (ioctl (fd, FIONREAD, &ret) != 0)
        return -1;
    return ret;
}

Вертает количество доступных байт для чтения... В топку неблокирующие сокеты...

Это сообщение отредактировал(а) GrayCardinal - 24.6.2009, 15:10


--------------------
PM MAIL WWW   Вверх
Alca
Дата 24.6.2009, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Цитата

Вертает количество доступных байт для чтения... В топку неблокирующие сокеты..

Прикольно


--------------------
PM WWW ICQ Skype Jabber   Вверх
fry
Дата 24.6.2009, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 257
Регистрация: 4.10.2006

Репутация: нет
Всего: 3



Цитата

__export int DIONREAD (int fd)
{
    int ret = -1;
    if (ioctl (fd, FIONREAD, &ret) != 0)
        return -1;
    return ret;
}

Вертает количество доступных байт для чтения... В топку неблокирующие сокеты...


В топку тогда еще и ioctl с дополнительным системным вызовом.
PM MAIL   Вверх
SVN74
Дата 25.6.2009, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18



Вот есть маленький примерчик (рабочий) принятия сообщений...
=====================================================
Код

bool TSockTCPServer::SendTCPMessage(SOCKET inSock, char* Buff)
{
    if(Buff == NULL) return false;
    if(strlen(Buff)==0) return false;
    int ChCount = strlen(Buff);
    if(!SendINT(inSock,&ChCount))
     {
        return false;
     }
    if(WriteBytesFull(inSock,Buff,ChCount) != ChCount)
     {
        return false;
     }
  return true;
}
//---------------------
bool TSockTCPServer::RecvTCPMessage(SOCKET inSock, char* Buff)
{
    if(Buff == NULL) return false;
    int ChCount = 0;
    if(!RecvINT(inSock,&ChCount))
     {
        return false;
     }
     memset(Buff,0,ChCount);
     if(ReadBytesFull(inSock,Buff,ChCount)!=ChCount)
     {
       return false;
     }
     Buff[ChCount] = 0;
  return true;
}
//---------------------------
int TSockTCPServer::ReadBytesFull(SOCKET inSock, char* Buff, int SizeBuff)
{
    if(Buff == NULL) return false;
    int rc;
    int x=0;
        memset(&Buff[0],0,SizeBuff);
        while(SizeBuff > 0)
        {
            rc = recv(inSock, &Buff[x], SizeBuff,0);
            if(rc == SOCKET_ERROR)
            {
               strcpy(ErrMess,GetWsaError());
               return rc;
            }
            if(rc == 0)    break;
           x += rc;
           SizeBuff -= rc;
        }
return x;
}

PM MAIL WWW   Вверх
Alca
Дата 25.6.2009, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Можно по-подробнее про дополнительные системные вызова?


--------------------
PM WWW ICQ Skype Jabber   Вверх
vinick
Дата 25.6.2009, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 285
Регистрация: 9.6.2005

Репутация: 6
Всего: 22



Цитата(Alca @  25.6.2009,  10:06 Найти цитируемый пост)
Можно по-подробнее про дополнительные системные вызова? 

При неблокирующих сокетах и select(), за один системный вызов можно проверить состояние множества сокетов. При использовании ioctl(FIONREAD), придется для каждого сокета делать системный вызов. 

При использовании select, процесс спит до наступления события. При использовании ioctl придется самому усыплять или как-то иначе занимать процесс и самому ловить момент когда сделать вызов.

Системный вызов это дорогая операция и лишний раз ее лучше не делать.
PM MAIL ICQ Jabber   Вверх
GrayCardinal
Дата 25.6.2009, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

Репутация: 3
Всего: 58



vinick
Кто мешает делать select + FIONREAD на блокирующих ?

Добавлено через 2 минуты и 25 секунд
vinick
ИМХО, ты бредишь  smile  

Это сообщение отредактировал(а) GrayCardinal - 25.6.2009, 13:17


--------------------
PM MAIL WWW   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1368 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.