c++ - imap 客户端 - 如何编写正确的请求?

标签 c++ sockets openssl imap winsock

我正在尝试使用 winsock/OpenSSL 制作简单的 IMAP 客户端,这是否可以在没有额外库的情况下实现?如果是这样,如何发送请求并得到响应?服务器只响应一次,即使没有请求,之后我发送请求和应用程序卡在 SSL_read(..) 函数,而不是超时和 BYE。如何发出正确的请求? enter image description here

bool RequestQueue(const char* serverName)
{
    SOCKET      hSocket = INVALID_SOCKET;
    char        receiveBuf[512];
    ZeroMemory(receiveBuf,512); 
    char        requestBuf[512];
    ZeroMemory(requestBuf,512); 
    sockaddr_in sockAddr = {0};
    bool        bSuccess = true;

    //SSL
    SSL* ssl;
    SSL_CTX* ctx;

    try
    {       
        //Look up hostname and fill sockaddr_in structure
        cout<< "Looking up hostname "<<serverName<<"...";
        FillSockAddr(&sockAddr,serverName,IMAP_SERVER_PORT);
        cout<< "found.\n";

        //creating socket
        cout<<"Creating socket..";
        if((hSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
            throw exception("could not create socket!");
        cout<<"created.\n";

            //Connect to server
        cout<<"Attempting to connect to "<< inet_ntoa(sockAddr.sin_addr)
            <<":"<<IMAP_SERVER_PORT<<" ...";
        if(connect(hSocket,(sockaddr*)(&sockAddr),sizeof(sockAddr))!= 0)
            throw exception("could not connect!");

        cout<<"connected\n";

        ctx = SSL_CTX_new(SSLv23_client_method());
        if(!ctx)
            throw exception("SSL_CTX_new error");

        ssl = SSL_new(ctx);
        SSL_CTX_free(ctx);
        if(!ssl)
            throw exception("ssl initializing error");

        SSL_set_fd(ssl,hSocket);
        if(SSL_connect(ssl) != 1)
            throw exception("SSL_connect error");

        int reqLen;
        int retLen;
        cout<<"==============\n";
        cout<<"====begin=====\n";
        cout<<"==============\n";

        retLen = SSL_read(ssl,receiveBuf,sizeof(receiveBuf));
        if(retLen<0)
            throw exception("SSL_read error.");
        cout<<"S: "<<receiveBuf;

        strcpy(requestBuf,"a001 CAPABILITY");
        reqLen = strlen(requestBuf);
        SSL_write(ssl,requestBuf,reqLen);
        cout<<"C: "<<requestBuf<<endl;  

        ZeroMemory(receiveBuf,sizeof(receiveBuf));
        retLen = SSL_read(ssl,receiveBuf,sizeof(receiveBuf));
        if(retLen<0)
            throw exception("SSL_read error.");

        cout<<"S: "<<receiveBuf;                    
    }
    catch(exception e)
    {
        cout<<"Error : "<<e.what()<<endl;
    }
    if(hSocket != INVALID_SOCKET)
    {
        SSL_shutdown(ssl);
        closesocket(hSocket);
        SSL_free(ssl);      
    }

    return bSuccess;
}

最佳答案

我没有深入分析您的代码,但我可以看出一个明显的问题。 根据RFC 3501 :

All interactions transmitted by client and server are in the form of lines, that is, strings that end with a CRLF. The protocol receiver of an IMAP4rev1 client or server is either reading a line, or is reading a sequence of octets with a known count followed by a line.

在您的代码中,您没有使用 CRLF 终止命令。尝试更换

strcpy(requestBuf,"a001 CAPABILITY");

strcpy(requestBuf,"a001 CAPABILITY\r\n");

此外,您最好在没有 SSL 的情况下开始,然后再添加它 - 这将大大简化调试(即使用 Wireshark )。

关于c++ - imap 客户端 - 如何编写正确的请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13776459/

相关文章:

c++ - 英特尔自动矢量化行程计数解释?

c++ - 使用 cout 和字符串格式化列

读取套接字时Java中断线程

encryption - Openssl:使用私钥解密,设置oaep

c++ - boost asio - 来自一个线程的 SSL async_read 和 async_write

c++ - 如果 HWND 窗口仍然存在,我该如何确定

c++ - std::map 或类似数据结构中的键压缩

c - 建立多个连接时如何在C中设置套接字超时?

java - 回收 DatagramPacket 对象安全吗?

openssl - 在centos 6.3上安装openssl