第 2 章 - 安装和使用 NetX Duo POP3 客户端

NetX POP3 客户端包括一个源文件、一个头文件和一个演示文件。 其中有两个用于 MD5 摘要式服务的附加文件。 此外,还有一个用户指南 PDF 文件(本文档)。

  • nxd_pop3_client.c:用于 NetX Duo POP3 客户端 API 的 C 源文件
  • nxd_pop3_client.h:用于 NetX Duo POP3 客户端 API 的 C 头文件
  • demo_netxduo_pop3_client.c:用于 POP3 客户端创建和会话启动的演示文件
  • nx_md5.c:定义 MD5 摘要式服务的 C 源文件
  • nx_md5.h:定义 MD5 摘要式服务的 C 头文件
  • nxd_pop3_client.pdf:NetX Duo POP3 客户端用户指南

若要使用 NetX Duo POP3 客户端,可将之前提到的全部分发文件复制到安装了 NetX Duo 的目录中。 例如,如果 NetX Duo 安装在目录“\threadx\mcf5272\green”中,则应将 nx_md5.h、nx_md5.c、nxd_pop3_client.h 和 nxd_pop3_client.c 文件复制到此目录中。

使用 NetX Duo POP3 客户端

若要使用 NetX Duo POP3 客户端服务,应用程序必须将 nxd_pop3_client.c 添加到其生成项目中。 应用程序代码的 tx_api.h 和 nx_api.h 后面必须加入 nx_md5.h 和 nxd_pop3_client.h,才能使用 ThreadX 和 NetX。

这些文件的编译方式必须与其他应用程序文件相同,并且对象代码必须与应用程序的文件链接起来。 这就是使用 NetX Duo POP3 客户端所需执行的所有操作。

NetX Duo POP3 客户端的小型示例

下面的图 1 是一个示例,演示了如何使用 NetX Duo POP3 客户端服务。 此演示在第 37 行和第 38 行设置两个回调,用于提供邮件下载和会话完成通知。 在第 76 行创建 POP3 客户端数据包池。 在第 88 行创建 IP 线程任务。 请注意,此数据包池也可用于 POP3 客户端数据包池。 在第 107 行的 IP 任务中启用 TCP。

在第 133 行的应用程序线程入口函数 demo_thread_entry 中创建 POP3 客户端。 这是因为 nx_pop3_client_create 服务也会尝试与 POP3 服务器建立 TCP 连接。 如果成功,应用程序会使用第 149 行的 nx_pop3_client_mail_items_get 服务,在 POP3 服务器上查询其邮箱中的项目数。

如果有一个或多个项目,则应用程序会对每个邮件项反复执行 while 循环,以下载邮件。 在第 149 行,通过 nx_pop3_client_mail_item_get 调用发出 RETR 请求。 如果成功,应用程序会使用第 177 行的 nx_pop3_client_mail_item_message_get 服务下载数据包,直至在收到的消息中检测到最后一个数据包(第 196 行)。 最后,如果成功下载,应用程序会通过第 199 行的 nx_pop3_client_mail_item_delete 调用删除邮件项。 RFC 1939 建议 POP3 客户端指示服务器删除下载的邮件项,以防客户端邮箱中的邮件堆积。 不过服务器可能会自动执行此操作。

下载所有邮件项后,或在 POP3 客户端服务调用失败的情况下,应用程序会退出循环,并使用 nx_pop3_client_delete 服务删除 POP3 客户端(第 217 行)。

/*
   demo_netxduo_pop3.c

   This is a small demo of POP3 Client on the NetX Duo TCP/IP stack.
   This demo relies on Thread, NetX Duo and POP3 Client API to conduct
   a POP3 mail session.
 */

#include  "tx_api.h"
#include  "nx_api.h"
#include  "nxd_pop3_client.h"

#define DEMO_STACK_SIZE             4096
#define CLIENT_ADDRESS              IP_ADDRESS(192,2,2,61)
#define SERVER_ADDRESS              IP_ADDRESS(192,2,2,89)
#define SERVER_PORT                 110

/* Replace the 'ram' driver with your own Ethernet driver. */
void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);

/* Set up the POP3 Client.  */

TX_THREAD           demo_client_thread;
NX_POP3_CLIENT      demo_client;
NX_PACKET_POOL      client_packet_pool;
NX_IP               client_ip;

#define PAYLOAD_SIZE 500

/* Set up Client thread entry point. */
void    demo_thread_entry(ULONG info);


  /* Shared secret is the same as password. */

#define LOCALHOST                               "recipient@domain.com"
#define LOCALHOST_PASSWORD                      "testpwd"

/* Define main entry point.  */
int main()
{
    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
}

/* Define what the initial system looks like.  */
void    tx_application_define(void *first_unused_memory)
{

    UINT     status;
    UCHAR    *free_memory_pointer;


    /* Setup the working pointer.  */
    free_memory_pointer =  first_unused_memory;

    /* Create a client thread.  */
    tx_thread_create(&demo_client_thread, "Client", demo_thread_entry, 0,
                     free_memory_pointer, DEMO_STACK_SIZE, 1, 1,
                     TX_NO_TIME_SLICE, TX_AUTO_START);

    free_memory_pointer =  free_memory_pointer + DEMO_STACK_SIZE;

    /* Initialize the NetX system.  */
    nx_system_initialize();

    /* The demo client username and password is the authentication
       data used when the server attempts to authentication the client. */

    /* Create Client packet pool. */
    status =  nx_packet_pool_create(&client_packet_pool,"POP3 Client Packet Pool",
                                    PAYLOAD_SIZE, free_memory_pointer,
                                    (PAYLOAD_SIZE * 10));
    if (status != NX_SUCCESS)
    {
        return;
    }

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer = free_memory_pointer + (PAYLOAD_SIZE * 10);


    /* Create IP instance for demo Client */
    status = nx_ip_create(&client_ip, "POP3 Client IP Instance",
                          CLIENT_ADDRESS, 0xFFFFFF00UL, &client_packet_pool,
                          _nx_ram_network_driver, free_memory_pointer,
                          2048, 1);

    if (status != NX_SUCCESS)
    {
        return;
    }

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer =  free_memory_pointer + 2048;

    /* Enable ARP and supply ARP cache memory. */
    nx_arp_enable(&client_ip, (void **) free_memory_pointer, 1024);

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer = free_memory_pointer + 1024;

    /* Enable TCP and ICMP for Client IP. */
    nx_tcp_enable(&client_ip);
    nx_icmp_enable(&client_ip);

    return;
}



/* Define the application thread entry function. */

void    demo_thread_entry(ULONG info)
{

    UINT        status;
    UINT        mail_item, number_mail_items;
    UINT        bytes_downloaded = 0;
    UINT        final_packet = NX_FALSE;
    ULONG       total_size, mail_item_size, bytes_retrieved;
    NX_PACKET   *packet_ptr;

    /* Let the IP instance get initialized with driver parameters. */
    tx_thread_sleep(40);


    /* Create a NetX POP3 Client instance with no byte or block memory pools.
       Note that it uses its password for its APOP shared secret. */
    status =  nx_pop3_client_create(&demo_client,
                                    NX_TRUE,
                                    &client_ip, &client_packet_pool, SERVER_ADDRESS,
                                    SERVER_PORT, LOCALHOST, LOCALHOST_PASSWORD);

    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        status = nx_pop3_client_delete(&demo_client);

        /* Abort. */
        return;
    }

    /* Find out how many items are in our mailbox.  */
    status = nx_pop3_client_mail_items_get(&demo_client, &number_mail_items,
                                            &total_size);

    printf("Got %d mail items, total size%d \n", number_mail_items, total_size);

    /* If nothing in the mailbox, disconnect. */
    if (number_mail_items == 0)
    {

        nx_pop3_client_delete(&demo_client);

        return;
    }

    /* Download all mail items.  */
    mail_item = 1;

    while (mail_item <= number_mail_items)
    {


        /* This submits a RETR request and gets the mail message size. */
        status = nx_pop3_client_mail_item_get(&demo_client, mail_item,
                                               &mail_item_size);

        /* Loop to get all mail message packets until the mail item is completely
           downloaded. */
        while((final_packet ==  NX_FALSE) && (status == NX_SUCCESS))
        {

            status = nx_pop3_client_mail_item_message_get(&demo_client, &packet_ptr,
                                                        &bytes_retrieved,
                                                        &final_packet);

            if (status != NX_SUCCESS)
            {

                break;
            }

            if (bytes_retrieved != 0)
            {

                printf("Received %d bytes of data for item %d: %s\n",
                        packet_ptr -> nx_packet_length,
                        mail_item, packet_ptr -> nx_packet_prepend_ptr);
            }

            nx_packet_release(packet_ptr);

            /* Determine if this is the last data packet. */
            if (final_packet)
            {
                /* It is. Let the server know it can delete this mail item. */
                status = nx_pop3_client_mail_item_delete(&demo_client, mail_item);
            }

            /* Keep track of how much mail message data is left. */
            bytes_downloaded += bytes_retrieved;
        }

        /* Get the next mail item. */
        mail_item++;

        tx_thread_sleep(100);

    }

    /* Disconnect from the POP3 server. */
    status = nx_pop3_client_quit(&demo_client);

    /* Delete the POP3 Client.  This will not delete the Client packet pool. */
    status = nx_pop3_client_delete(&demo_client);

}

图 1. NetX Duo POP3 客户端应用程序的示例

POP3 客户端配置选项

NetX Duo POP3 客户端有多个配置选项。 下面是详细描述的所有选项的列表:

  • NX_POP3_CLIENT_PACKET_TIMEOUT:此选项定义 POP3 客户端分配数据包时的等待选项(以秒为单位)。 默认值为 1 秒钟。
  • NX_POP3_CLIENT_CONNECTION_TIMEOUT:此选项定义 POP3 客户端连接到 POP3 服务器时的等待选项(以秒为单位)。 默认值为 30 秒。
  • NX_POP3_CLIENT_DISCONNECT_TIMEOUT:此选项定义 POP3 客户端断开与 POP3 服务器的连接时的等待选项(以秒为单位)。 默认值为 2 秒。
  • NX_POP3_TCP_SOCKET_SEND_WAIT:此选项在 nx_tcp_socket_send 服务调用中设置等待选项(以秒为单位)。 默认值为 2 秒。
  • NX_POP3_SERVER_REPLY_TIMEOUT:此选项在 nx_tcp_socket_receive 服务调用中设置服务器回复客户端请求时的等待选项。 默认值为 10 秒。
  • NX_POP3_CLIENT_TCP_WINDOW_SIZE:此选项设置客户端 TCP 接收窗口的大小。 此选项应设置为 IP 实例 MTU 大小减去 IP 和 TCP 标头的值。 默认值为 1460。 如果应用程序通过 IPv6 发送 POP3 数据包(1440 字节),则应当将该值设置为更小的值,因为 IPv6 标头较大。
  • NX_POP3_MAX_USERNAME:此选项设置 POP3 客户端用户名的缓冲区大小。 默认值为 40 字节。
  • NX_POP3_MAX_PASSWORD:此选项设置 POP3 客户端密码的缓冲区大小。 默认值为 20 字节。