Handeling SSL客户端无法读取所有数据

时间:2015-08-26 23:26:31

标签: c++ sockets ssl openssl server

我试图完成,我的ssl服务器没有崩溃,当客户端没有收集所有数据时。 (修正了一个小错误)
当数据太长时。

基本上我尝试做的是以非阻塞的方式写。 为此,我发现了两种不同的方法:

第一种方法
使用此代码

int flags = fcntl(ret.fdsock, F_GETFL, 0);
fcntl(ret.fdsock, F_SETFL, flags | O_NONBLOCK);

并用它创建ssl连接

第二种方法:
使用SSL_new(ctx)

创建SSL对象后直接执行此操作
BIO *sock = BIO_new_socket(ret.fdsock, BIO_NOCLOSE);
BIO_set_nbio(sock, 1);
SSL_set_bio(client, sock, sock);

这两者都有其缺点,但两者都没有帮助解决问题 第一种方法似乎以无阻塞的方式读取,但是当我写入的数据多于客户端读取数据时,我的服务器崩溃了。
第二种方法似乎没有做任何事情,所以我的猜测是,我做错了什么或者不明白BIO究竟做了什么。

有关更多信息,请参阅服务器如何写入客户端:

int SSLConnection::send(char* msg, const int size){
    int rest_size = size;
    int bytes_sent = 0;
    char* begin = msg;
    std::cout << "expected bytes to send: " << size << std::endl;
    while(rest_size > 0) {
        int tmp_bytes_sent = SSL_write(connection, begin, rest_size);
        std::cout << "any error     : " << ERR_get_error()<< std::endl;
        std::cout << "tmp_bytes_sent: " << tmp_bytes_sent << std::endl;
        if (tmp_bytes_sent < 0){
            std::cout << tmp_bytes_sent << std::endl;
            std::cout << "ssl error     : " << SSL_get_error(this->connection, tmp_bytes_sent)<< std::endl;
        } else {
            bytes_sent += tmp_bytes_sent;
            rest_size -= tmp_bytes_sent;
            begin = msg+bytes_sent;
        }
    }
    return bytes_sent;
}

输出:

expected bytes to send: 78888890
Betätigen Sie die <RETURN> Taste, um das Fenster zu schließen...
(means: hit <return> to close window)

编辑: 人们说,我需要缓存错误,这是我的新代码:

设定:

connection = SSL_new(ctx);
if (connection){
    BIO * sbio = BIO_new_socket(ret.fdsock, BIO_NOCLOSE);
    if (sbio) {
        BIO_set_nbio(sbio, false);
        SSL_set_bio(connection, sbio, sbio);
        SSL_set_accept_state(connection);
    } else {
        std::cout << "Bio is null" << std::endl;
    }
} else {
    std::cout << "client is null" << std::endl;
}

发送:

int SSLConnection::send(char* msg, const int size){
    if(connection == NULL) {
        std::cout << "ERR: Connection is NULL" << std::endl;
        return -1;
    }
    int rest_size = size;
    int bytes_sent = 0;
    char* begin = msg;
    std::cout << "expected bytes to send: " << size << std::endl;
    while(rest_size > 0) {
        int tmp_bytes_sent = SSL_write(connection, begin, rest_size);
        std::cout << "any error     : " << ERR_get_error()<< std::endl;
        std::cout << "tmp_bytes_sent: " << tmp_bytes_sent << std::endl;
        if (tmp_bytes_sent < 0){
            std::cout << tmp_bytes_sent << std::endl;
            std::cout << "ssl error     : " << SSL_get_error(this->connection, tmp_bytes_sent)<< std::endl;
            break;
        } else if (tmp_bytes_sent == 0){
            std::cout << "tmp_bytes are 0" << std::endl;
            break;
        } else {
            bytes_sent += tmp_bytes_sent;
            rest_size -= tmp_bytes_sent;
            begin = msg+bytes_sent;
        }
    }

    return bytes_sent;
}

使用提取60个字节的客户端,这里是输出:

输出写入1,000,000字节:

expected bytes to send: 1000000
any error     : 0
tmp_bytes_sent: 16384
any error     : 0
tmp_bytes_sent: 16384
Betätigen Sie die <RETURN> Taste, um das Fenster zu schließen...
(translates to: hit <RETURN> to close window)

输出写入1,000字节:

expected bytes to send: 1000
any error     : 0
tmp_bytes_sent: 1000
connection closed  <- expected output

1 个答案:

答案 0 :(得分:1)

我认为你的问题是

rest_size - = bytes_sent;

你应该做rest_size - = tmp_bytes_sent;

另外

if (tmp_bytes_sent < 0){
            std::cout << tmp_bytes_sent << std::endl;
           //its an error condition
          return bytes_sent;
        }

我不知道这是否能解决问题,但您粘贴的代码有上述问题