Как прекратить операцию чтения в Boost asio - PullRequest
0 голосов
/ 22 июля 2011

Использование MS VC ++ C: 9 (2008) в Windows XP 32 бита и Boost.asio:

Я написал приложение, которое может отправлять / получать электронную почту с / на проприетарную базу данных dBase, используяПротоколы POP3 / SMTP.Все это работает, как и ожидалось, но в процессе подключения SMTP есть проблема, которую на данный момент мне не удалось устранить в общем виде.

В SMTP весь процесс представляет собой последовательностькоманды от клиента (C :) и чтение ответов с удаленного сервера (S :).Команда отправляется с некоторыми значениями:

async_write (socket_, request_,
    boost::bind(&IPCON::hndlSOKresp, this, placeholders::error));

Ответ сервера на команду клиента всегда заканчивается последовательностью CRLF, поэтому функция hdlSOKresp () включает некоторые из них:

async_read  (socket_,  response_,  transfer_at_least(1),
     boost::bind(&IPCON::hndlRemain,  this,  placeholders::error));

В свою очередь, hadlRemain () проверяет, заканчивается ли принятый буфер парой CRLF, и в противном случае рекурсивно вызывает себя, пока не будет получен весь ответ.

Схема работает нормально, когда, как правило,Ответ сервера содержит одну строку, но команда EHLO / HELLO выдает многострочный ответ, содержащий основные характеристики сервера и специфику каждого сервера.Например, есть древовидные ответы:

1 & 1 Сервер Nemesis (провайдер интернет-услуг):

250-smtp.1and1.es
250-STARTTLS
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-PIPELINING
250-SIZE 120000000
250 HELP

Google Gmail:

250-mx.google.com at your service, [83.61.174.109]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH
250 ENHANCEDSTATUSCODES

Yahoo:

250-smtp212.mail.bf1.yahoo.com
250-AUTH LOGIN PLAIN XYMCOOKIE
250-PIPELINING
250 8BITMIME

Вопрос в том, как можно справиться с этой ситуацией?

Временное решение состоит в том, что если я знаю используемое соединение, то я могу ждать до последнего слова.То есть: если используется Gmail, соединение может продолжить чтение, пока не будет получено слово «ENHANCEDSTATUSCODES \ r \ n», и весь процесс будет продолжен как чудо-вызов.Но очевидно, что это не практичный вариант.

Другой подход заключался в том, чтобы включить эту конкретную команду в блок try / catch и использовать таймер для прерывания процесса чтения через некоторое время.Например:

// the connection-object panelp is defined here -out of the try/catch block-
try {
    if (!smtpConnect (panelp))  {
        // throw some error…
    }
} catch (...) {
    // if (error == connection timed-out) then continue
}

// the process continues here

Проблема здесь в том, что если продолжить работу после исключения, процесс зависнет в следующей операции asio.Кажется, что раскрутка стека как-то повлияла на поведение asio.

1 Ответ

4 голосов
/ 22 июля 2011

См. Этот документ: SMTP-многострочные ответы :

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

...