【发布时间】:2015-08-26 23:26:31
【问题描述】:
我正在努力实现,我的 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)
输出写入 1000 字节:
expected bytes to send: 1000
any error : 0
tmp_bytes_sent: 1000
connection closed <- expected output
【问题讨论】:
-
不,遗憾的是没有-1,这就是重点。这只是一个临时打印输出,一旦我收到错误返回,它将被删除。崩溃意味着崩溃。服务器只是停止。就像一个段错误,但不显示它。
-
崩溃是意外退出。你是这个意思吗?在我看来,您没有崩溃而是无限循环的可能性更大。看我的回答。注意错误报告代码永远不会是“临时的”,并且必须始终显示实际错误,而不仅仅是 -1 症状。
-
“Betätigen Sie die
Taste, um das Fenster zu schließen...”。请翻译。本网站以英语进行。 -
对不起,只是表示“点击
关闭窗口”,它是QtCreator的输出;) -
是不是管道坏了?你设置好你的信号处理器了吗?
标签: c++ sockets ssl openssl server