Closed Zjek closed 3 years ago
Hi Zjek,
Coding advices
First of all, you should consider RAII when dealing with memory allocation.
kademlia::session *s;
->
std::unique_ptr<kademlia::session> s;
You don't have to allocate every attribute with a new
, for instance, you can change the main_loop_result
attribute type from
std::future<std::error_code> *main_loop_result;
->
std::future<std::error_code> main_loop_result;
(dropped the pointer).
And write within your Widget constructor as follow:
main_loop_result = new std::future<std::error_code>(std::async(std::launch::async,
&kademlia::session::run,s));
->
main_loop_result = std::async(std::launch::async, &kademlia::session::run, s.get());
Your error
Could you elaborate on the error. Is it a runtime error or a compilation error ? In both cases, would you paste the error text ?
Hi @DavidKeller,
That was my mistake. I ran two programs. There was no problem with the first program.But there was an error in the second program.In the second program, I just modified the IP and port.
My code
#include "widget.h"
#include "ui_widget.h"
#include<kademlia/session.hpp>
#include<future>
#include<QDebug>
#include<iostream>
#include<kademlia/error.hpp>
#include<QHostInfo>
#include<QFile>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
kademlia::endpoint const initial_peer{"1.2.3.4", 27980};
/*I use a debugger to debug the code.There was an error when my second program got here.
The inferior stopped because it triggered an exception.
Stopped in thread 0 by:Exception at 0x7ff837823b29,code:0xe06d7363:c++exception,
flags=0x1(execution cannot be continued).*/
-> std::unique_ptr<kademlia::session> c (new kademlia::session{initial_peer});
s = std::move(c);
main_loop_result = std::async(std::launch::async, &kademlia::session::run, s.get());
//qDebug()<<"type: "<<typeid (main_loop_result).name();
ui->setupUi(this);
}
Widget::~Widget()
{
s->abort();
// auto failure = main_loop_result->get();
// if(failure!=kademlia::RUN_ABORTED)
// qDebug()<<QString::fromStdString(failure.message());
delete ui;
}
void Widget::on_searchButton_clicked()
{
QByteArray bytes("key");
std::vector<uint8_t> key(bytes.begin(),bytes.end());
auto on_load = [](std::error_code const& failure
,kademlia::session::data_type const& data)
{
qDebug()<<"data: "<<data.data();
if(failure)
qDebug()<<QString::fromStdString(failure.message());
else
std::copy(data.begin(),data.end()
,std::ostream_iterator<std::uint32_t>{std::cout," "});
};
s->async_load(key,on_load);
}
void Widget::on_saveButton_clicked()
{
QFile file("D:/qt_code/222.txt");
if(!file.open(QFile::ReadOnly)){
qDebug()<<"open file error!";
return;
}
QByteArray block;
block = file.readAll();
file.close();
std::vector<uint8_t> txt(block.begin(),block.end());
kademlia::session::data_type const data{txt.begin(),txt.end()};
auto on_save = [](std::error_code const& failure){
if(failure)
qDebug()<<QString::fromStdString(failure.message());
};
QByteArray bytes("key");
std::vector<uint8_t> key(bytes.begin(),bytes.end());
s->async_save(key,data,on_save);
}
My error
abort() has been called (Press Retry to debug the application)
Question How can I print information about another discovered node.
Hum this is where the project is lacking some documentation. I'll will fix that.
Your error
I believe the std::abort()
is called because an exception is thrown from the initial peer discovery code as it can't be reached at 1.2.3.4:27980.
When a session
is created, an initial_peer is required as first argument. This is the first neighbor node the current node will contact in order to discover other nodes.
To create the initial_peer node, a session
object can't be used because it requires... an initial_peer. But the first_session
(include/kademlia/first_session.hpp) class doesn't requires an initial_peer and should be used to create the first node.
This first_session
class is required to bootstrap the network. Once there is more than one initial_peer node in the network, the initial_peer node can be shut down.
So in your case, you should create a another application which instantiates a first_session
. It can be a small console application or another full fledged Qt Application, or even a parameter of your current Qt Application to select between two behaviors.
Another point is that by default session
& first_session
listen for 0.0.0.0:27980 & [::]:27980. So if you run the bootstrap and the main application on the same host, you have to ensure ports or IPs are unique.
Answer to your question
You can't get information about discovered nodes from the API. In order to keep it dead simple, all the node discovery work is hidden. If that's a piece of information important to you, you may have a look at other C++ kademlia implementations on github. I've seen some very interesting projects.
But you only want to see the discovery for debugging purpose, can enable debug logging by compiling with KADEMLIA_ENABLE_DEBUG
defined.
Hello,@DavidKeller!
My mistake has not been solved. Can you give me a complete example?
first_session
kademlia::first_session first;
auto result = std::async(std::launch::async,
&kademlia::first_session::run,
&first);
first.abort();
auto failure = result.get();
if(failure.value() == kademlia::RUN_ABORTED)
{
qDebug()<<QString::fromStdString(failure.message());
}
the first session
namespace k = kademlia;
k::endpoint const initial_peer{"192.168.1.33",6666};
std::unique_ptr<k::session>c(new k::session(initial_peer));
s=std::move(c);
auto q = std::async(std::launch::async,&k::session::run,s.get());
s->abort();
auto e = q.get();
if(e == kademlia::RUN_ABORTED)
{
qDebug()<<QString::fromStdString(e.message());
}
the second session
namespace k = kademlia;
k::endpoint const initial_peer{"192.168.1.77",55556};
std::unique_ptr<k::session>c(new k::session(initial_peer));
s=std::move(c);
auto q = std::async(std::launch::async,&k::session::run,s.get());
s->abort();
auto e = q.get();
if(e == kademlia::RUN_ABORTED)
{
qDebug()<<QString::fromStdString(e.message());
}
I created a frist_session and two session .When I created the second session, the abort () was called;
Your code starts the session processing loops and aborts them right away:
auto q = std::async(std::launch::async,&k::session::run,s.get());
// TODO: Wait on something here (like a signal, a key pressed, a timeout, whatever)
s->abort();
auto result = std::async(std::launch::async,
&kademlia::first_session::run,
&first);
// Wait here as well
first.abort();
You should wait for something between the start and the abort.
@DavidKeller The bug was fixed. My question How does this library transfer files?Is it transmitted by multiple clients or end-to-end?How can I debug and print peers' ip or port.I added "#define KADEMLIA_ENABLE_DEBUG " at the top of the cpp file.But there is nothing to display.
.
Thanks!
Hello Zjek, I've written a documentation for you here: https://kademlia-cpp.readthedocs.io/en/latest/?badge=master
This library won't be efficient to transfer files.
It allows to associate a value with a key. If you want to transfer files with the maxim throughput, you should store them on a host with a high bandwidth (like a server living in a datacenter), and use this library to save the stored file URL.
Other client will find the file URL using kademlia, but will perform the fetching using the protocol you selected (e.g. http, ftp, bittorrent) when you uploaded the file on the high bandwidth host.
Hello!
There was an error when I ran two of these programs. Another program modifies the IP and port.
Compiling environment:QT5.12 widget.h:
widget.cpp:
Thanks!