проблема с winsock
От: Evilguc  
Дата: 07.10.08 13:05
Оценка:
Вот пишу длл-плагин к программе, который должен коннектится к серверу отправлять данные и получать ответ от сервера. Столкнулся со следующей проблемой:
при использовании для получения данных из системного буфера функции recv можно "повесить" длл если данные от сервера не приходят, т.е программа ждет появления данных в буфере и на этом стопориться, например:

...
        WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2),&wsaData);
    SOCKET sock;
    char buffer[1024], buffer2[1024];
    struct sockaddr_in addr;
    if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET)
    {
        addr.sin_family = AF_INET;
        addr.sin_port = htons(12345);
        addr.sin_addr.s_addr = inet_addr(ip);
        if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != SOCKET_ERROR)
        {
            send(sock, buffer, sizeof(buffer), 0);
            recv(sock, buffer2, sizeof(buffer2), 0); // здесь в случае, если данные от сервера не придут(если сервер не отправит их,
                                                                 //   а не в случаи ошибки или дисконнекта), и будет стопор
        }
        return -1;
    }
...

Как можно сделать чтоб в случае не получения данных какое-то время или буквально сразу узнать об этом и просто их(данных) не дожидаться?
Еще раз оговорюсь, что функцию выполняет длл и если данные не приходят, надо отдавать управление программе! Это очень важно!
Спасибо!


07.10.08 19:14: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: проблема с winsock
От: Conr Россия  
Дата: 07.10.08 13:13
Оценка:
Здравствуйте, Evilguc, Вы писали:

E>Как можно сделать чтоб в случае не получения данных какое-то время или буквально сразу узнать об этом и просто их(данных) не дожидаться?

Вариантов много. Можно, например, вначале вызывать select, чтобы узнать — а есть ли данные.
Re[2]: проблема с winsock
От: Evilguc  
Дата: 07.10.08 13:56
Оценка:
Здравствуйте, Conr, Вы писали:

C>Вариантов много. Можно, например, вначале вызывать select, чтобы узнать — а есть ли данные.


Как понимаю имеется в виду использование примерно такого кода

FD_SET set;
FD_ZERO(&set);
FD_SET(sock, &set);
int Ready;
Ready = select(0, &set, 0, 0, 0);
if (Ready == -1)
        MessageBox(0, 0, 0, 0);
else
{
   // to do somesing
}


Я правильно понял? Если да, то почемуто не хочет работать — стопориться также как и при recv
Если нет, то напиши как?
ИМХО если есть какие-то закавырки в использовании функции или кода, надо отписываясь ваять какой нить примерчик.
Re[3]: проблема с winsock
От: Conr Россия  
Дата: 07.10.08 14:31
Оценка:
Здравствуйте, Evilguc, Вы писали:

E>Как понимаю имеется в виду использование примерно такого кода


E>
E>FD_SET set;
E>FD_ZERO(&set);
E>FD_SET(sock, &set);
E>int Ready;
E>Ready = select(0, &set, 0, 0, 0);
E>if (Ready == -1)
E>        MessageBox(0, 0, 0, 0);
E>else
E>{
E>   // to do somesing
E>}
E>


E>Я правильно понял? Если да, то почемуто не хочет работать — стопориться также как и при recv

E>Если нет, то напиши как?
Последний параметр — это таймаут. Если это 0, то вызов блокируется. Плюс еще желательно за ошибками следить.

    FD_SET read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock, &read_fds);

    FD_SET err_fds;
    FD_ZERO(&err_fds);
    FD_SET(sock, &err_fds);

    timeval timeout;
    timeout.tv_sec=1; // если в течении 1 секунды данных нет, то выходим
    timeout.tv_usec=0;

    int result = select(0, &read_fds, 0, &err_fds, &timeout);
    if( SOCKET_ERROR == result || FD_ISSET(sock, &err_fds) )
    {
         // ошибки, логгируем и выходим
    }

    if( !FD_ISSET(sock, &read_fds) || 0 == result )
    {
         // читать нечего, выходим.
    }

    // данные есть, читаем...

E>ИМХО если есть какие-то закавырки в использовании функции или кода, надо отписываясь ваять какой нить примерчик.
В доках все есть, имхо, достаточно дать наводку.
Re[4]: проблема с winsock
От: Evilguc  
Дата: 07.10.08 14:53
Оценка:
Здравствуйте, Conr, Вы писали:

C>Последний параметр — это таймаут. Если это 0, то вызов блокируется. Плюс еще желательно за ошибками следить.


    FD_SET read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock, &read_fds);

    FD_SET err_fds;
    FD_ZERO(&err_fds);
    FD_SET(sock, &err_fds);

    timeval timeout;
    timeout.tv_sec=1; // если в течении 1 секунды данных нет, то выходим
    timeout.tv_usec=0;

    int result = select(0, &read_fds, 0, &err_fds, &timeout);
    if( SOCKET_ERROR == result || FD_ISSET(sock, &err_fds) )
    {
         // ошибки, логгируем и выходим
    }

    if( !FD_ISSET(sock, &read_fds) || 0 == result )
    {
         // читать нечего, выходим.
    }

    // данные есть, читаем...


Спасибо, буду пробовать...
А насчет того, что в документации все есть... в МСДН(оффлайн) смотрел, там только краткое описание, по нему смог только в целом понять принцип, а еще откопал у себя один русскоязычный справочник, так там примерно так как я написал в предыдущем сообщении. Вот так вот...
Re: проблема с winsock
От: Vamp Россия  
Дата: 09.10.08 14:14
Оценка:
В MSDN есть упоминание о recv с таймаутом, путем задания сокету параметра SO_RCVTIMEO.

SO_RCVTIMEO and SO_SNDTIMEO
When using the recv function, if no data arrives during the period specified in SO_RCVTIMEO, the recv function completes. In Windows versions prior to Windows 2000, any data received subsequently fails with WSAETIMEDOUT. In Windows 2000 and later, if no data arrives within the period specified in SO_RCVTIMEO the recv function returns WSAETIMEDOUT, and if data is received, recv returns SUCCESS.

If a send or receive operation times out on a socket, the socket state is indeterminate, and should not be used; TCP sockets in this state have a potential for data loss, since the operation could be canceled at the same moment the operation was to be completed.


Обратите внимание на выделенное, однако.
Да здравствует мыло душистое и веревка пушистая.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.