如何终止 Boost asio 中的读取操作

发布于 2024-11-25 19:22:09 字数 1786 浏览 3 评论 0原文

在 Windows XP 32 位和 Boost.asio 中使用 MS VC++ C:9 (2008):

我编写了一个应用程序,可以使用 POP3/SMTP 协议从专有 dBase 发送/接收电子邮件。整个事情按预期进行,但 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 行为。

Using MS VC++ C:9 (2008) in Windows XP 32 bits and Boost.asio:

I’ve written an application who can send/receive e-mails from/to an proprietary dBase using the POP3/SMTP protocols. The whole thing work as expected, but there are an problem in the SMTP connection process that for the moment, I’ve been unable to resolve in a generic way.

In SMTP, the whole process is a sequence of commands from the client (C:) and reading the responses from the remote server (S:). The command is sent with some as:

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

The server response to the client’s command, is always ended with CRLF sequence, so the hdlSOKresp() function, includes some as:

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

In turn, hadlRemain() verifies if the received buffer ends with the CRLF pair, and otherwise, calls itself recursively until the whole response has been received.

The schema work fine when -as usually-, the server response contains one line, but the command EHLO/HELLO, produce a multiline response containing the main characteristics of the server and specific of each server. As an example, there are tree responses:

1&1 Nemesis server (a knonw Internet service provider):

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

The question is: how can be handled this situation?

The momentary workaround is that if I know the connection that has been used, then I can wait until the last word. I.e: if Gmail is used, the connection can continue reading until the word “ENHANCEDSTATUSCODES\r\n” has been received and the whole process continues as a charm. But obviously this is not a practical option.

Another approach has been include this specific command in a try/catch block and use the timer to abort the reading process after a while. Some as:

// 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

The problem here is that if continuing after an exception, the process hang in the next asio operation. It seems as if the stack unwinding affected the asio behavior in some way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

作死小能手 2024-12-02 19:22:09

请参阅此文档:SMTP 多行响应

多行回复的格式要求每一行(除了
最后,以回复代码开头,紧接着是连字符“-”
(也称为减号),后跟文本。最后一行将以
回复代码,紧随其后的是,可选一些文本,

Please see this document: SMTP Multiline Reponses:

The format for multiline replies requires that every line, except the
last, begin with the reply code, followed immediately by a hyphen, "-"
(also known as minus), followed by text. The last line will begin with
the reply code, followed immediately by <SP>, optionally some text,
and <CRLF>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文