c++ - OpenSSL 偶尔会打印随机垃圾
问题描述
我刚刚开始使用 OpenSSL 来发出 HTTPS 请求。我正在使用 C++。有时,我会得到一个看起来像这样的正确响应:
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Sun, 09 Aug 2020 12:14:03 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 159
Connection: keep-alive
Access-Control-Allow-Credentials: true
Vary: Origin
{"status":"success","symbol":"AAPL","last":{"price":446.71,"size":200,"exchange":2,"cond1":14,"cond2":12,"cond3":41,"cond4":0,"timestamp":1596835355456000000}}
有时我会得到一个看起来像这样的有问题的响应:(向右滚动)
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Sun, 09 Aug 2020 12:14:06 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 159
Connection: keep-alive
Access-Control-Allow-Credentials: true
Vary: Origin
{"status":"success","symbol":"AAPL","last":{"price":446.71,"size":200,"exchange":2,"cond1":14,"cond2":12,"cond3":41,"cond4":0,"timestamp":15968353554560000?????`9??????p???????p?#???????`???????u???????@???????U?????? ??????5??????
我认为这个问题与向缓冲区添加内容的 SSL_read 函数有关,但我不确定。我知道这个问题并不特定于该网站,因为我尝试向其他网站发出请求并且得到了相同的结果。这是请求方法的代码:
Response* Requests::get(const char* ip_addr, std::string& route, datastructures::hash::HashTable& headers, datastructures::hash::HashTable& parameters){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_port = htons(443);
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ip_addr);
connect(sock, (struct sockaddr*)&server, sizeof(server));
cout<<SSL_load_error_strings()<<endl;
cout<<SSL_library_init()<<endl;
SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
SSL* conn = SSL_new(ctx);
cout<<SSL_set_fd(conn, sock)<<endl;
cout<<SSL_connect(conn)<<endl;
std::vector<datastructures::hash::Key> params = parameters.getTable();
std::vector<datastructures::hash::Key> heads = headers.getTable();
std::ostringstream os;
os << "GET " << route <<"?";
std::string request = os.str();
os.str("");
{
int i;
for(i=0;i<params.size();i++){
os << params[i].key << "="<< *(std::string*)(params[i].value) << "&";
request+=os.str();
os.str("");
}
request += " HTTP/1.1 \r\n";
request+=os.str();
for(i=0;i<heads.size();i++){
os << heads[i].key << ": " << *(std::string*)(heads[i].value) << "\r\n";
request+=os.str();
os.str("");
}
request += "\r\n";
}
SSL_write(conn, (const char*)request.c_str(), request.size());
std::string ret;
const char* retc = (const char*)malloc(10240*sizeof(char));
int recv = SSL_read(conn, (void *)retc, 10240);
while(true){
ret+=retc;
free((char*)retc);
if(recv < 10240){
break;
} else{
recv = SSL_read(conn, (void *)retc, 10240);
retc = (const char*)malloc(10240*sizeof(char));
}
}
SSL_free(conn);
close(sock);
return new Response(ret);
这是我在主函数中调用该方法的方式:
std::cout << requests::Requests::get("35.186.171.205", route, headers, parameters)->getRawResponse() << std::endl;
//Get raw response is a method in my response class that just returns the raw http response
解决方案
显示的代码中有多个错误。
ret+=retc;
只有当它指向的字符串由 a 终止时,retc
这才有效。不做任何事情。您应该使用'重载,它需要一个指针和一个确切数量的字符来添加到这个字符串中。char *
'\0'
SSL_read
std::string
append()
free((char*)retc);
// ...
recv = SSL_read(conn, (void *)retc, 10240);
retc = (const char*)malloc(10240*sizeof(char));
这个代码序列:
解除分配
retc
。该指针现在无效。尝试将某些内容读入
retc
,这不再有效。分配一个新的
retc
指针。
一个新的缓冲区应该在读入之前分配。此外,甚至没有必要一开始就完成所有这些工作。以前用于SSL_read
某些东西的缓冲区完全可以用于SSL_read
更多的东西。它完全适合这项工作。free
一个缓冲区,只是malloc
再一次,绝对没有任何用处。
最后,如果您真的打算编写现代 C++ 代码,则没有必要malloc
或free
任何事情。只需使用 astd::vector<char>
并让向量本身为您处理所有内存分配和释放。您很少在现代 C++ 代码中看到手动内存分配和释放,它使用容器来正确处理和正确跟踪所有内存,并自动清理它以避免内存泄漏。
只需将所有手动分配内存的实例替换为std::vector<char>
.
推荐阅读
- php - $_SESSION 没有在表单上选择正确的值
- python - 阻止 Visual Studio Code 激活 Python 虚拟环境
- ruby - Chartkick w/ Highcharts column_chart,按系列指定可见性
- javascript - 如何在 NetSuite 上的“删除”用户事件期间执行某些操作?
- c# - 当用户从浏览器下载 msi 时,如何将参数与 msi 一起传递?
- angular - 如何动态地从角度 6 中的嵌套 json 对象中获取值?
- python - crontab 重启权限
- python - 遍历 Python 字典并特殊追加到新列表?
- javascript - 从客户端使用变量加载文件
- php - Laravel 框架 php 中的路由冲突