不是C,不要使用new、malloc(或delete或free)。
具体来说,我看到了指向套接字的指针,指向一切的指针。如果您完成了分配工作,您会泄漏使用new 分配的整个缓冲区。
这是一个更简单的方法,减少双缓冲(streambuf 增加一点):
uint8_t buffer[10000];
auto transferred = boost::asio::read(
sock,
boost::asio::buffer(buffer),
boost::asio::transfer_all(),
ec);
现在成功后,tranferred 字节将在您分配的缓冲区中。更简单的
std::vector<uint8_t> buffer(10000);
因为这样你就可以简单地
buffer.resize(transferred);
Live On Coliru
#include <boost/asio.hpp>
#include <atomic>
#include <iostream>
#include <iomanip>
using boost::asio::ip::tcp;
using boost::asio::ip::address_v4;
int main() {
//uint8_t buffer[10000];
std::vector<uint8_t> buffer(10000);
boost::asio::io_context ioc;
tcp::socket sock(ioc);
sock.connect({address_v4::from_string("173.203.57.63"), 80});
write(sock, boost::asio::buffer("GET / HTTP/1.1\r\nHost: coliru.stacked-crooked.com\r\nConnection: close\r\n\r\n"));
boost::system::error_code ec;
auto transferred = boost::asio::read(
sock,
boost::asio::buffer(buffer),
boost::asio::transfer_all(),
ec);
if (ec && ec != boost::asio::error::eof) {
std::cout << "receive failed:" << ec.message() << std::endl;
} else {
buffer.resize(transferred);
std::cout << std::hex << std::showbase << std::setfill('0');
int n = 0;
for (int i : buffer) {
std::cout
<< std::setw(4) << i
<< " '" << char(std::isgraph(i)?i : '.') << "'"
<< (++n % 8? ' ':'\n');
}
}
}
打印
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
0x48 'H' 0x54 'T' 0x54 'T' 0x50 'P' 0x2f '/' 0x31 '1' 0x2e '.' 0x31 '1'
0x20 '.' 0x32 '2' 0x30 '0' 0x30 '0' 0x20 '.' 0x4f 'O' 0x4b 'K' 0x20 '.'
00xd '.' 00xa '.' 0x43 'C' 0x6f 'o' 0x6e 'n' 0x74 't' 0x65 'e' 0x6e 'n'
0x74 't' 0x2d '-' 0x54 'T' 0x79 'y' 0x70 'p' 0x65 'e' 0x3a ':' 0x20 '.'
0x74 't' 0x65 'e' 0x78 'x' 0x74 't' 0x2f '/' 0x68 'h' 0x74 't' 0x6d 'm'
... 1100 lines snipped
0x20 '.' 0x20 '.' 0x7d '}' 0x3b ';' 00xa '.' 0x3c '<' 0x2f '/' 0x73 's'
0x63 'c' 0x72 'r' 0x69 'i' 0x70 'p' 0x74 't' 0x3e '>' 00xa '.' 0x3c '<'
0x2f '/' 0x68 'h' 0x74 't' 0x6d 'm' 0x6c 'l' 0x3e '>' 00xa '.'
动态/堆分配
std::vector 已经进行了堆分配。如果您坚持原始 C 数组语义,请考虑 Live On Coliru:
auto buffer = std::make_unique<std::array<std::atomic<uint8_t, 10'000> > >();
// ...
boost::asio::buffer(*buffer),
// ...
size_t n = 0;
for (int i : *buffer) {
if (n>=transferred) break;
std::cout
<< std::setw(4) << i
<< " '" << char(std::isgraph(i)?i : '.') << "'"
<< (++n % 8? ' ':'\n');
}
甚至Live On Coliru:
auto buffer = std::make_unique<uint8_t[]>(10'000);
// ...
boost::asio::buffer(buffer.get(), 10'000),
// ...
size_t n = 0;
for (auto it = buffer.get(); it <= buffer.get() + transferred; ++it) {
std::cout
<< std::setw(4) << static_cast<int>(*it)
<< " '" << char(std::isgraph(*it)?*it : '.') << "'"
<< (++n % 8? ' ':'\n');
}
正如您所见,像这样使用“手动”缓冲区的操作更容易出错,但至少现在您没有内存泄漏。