How to parse network hostname + port in qt? - c++

I am currently writing a network application in Qt and need to seperate network adresses in the form:
example.org:1234
into seperate hostname and port QStrings.
Is there a Qt function to easily parse this and check if the given input is correct?
Thanks in advance!

This is quite simple; you just use the QUrl class for this with the constructor, host() and port() methods as follows:
QUrl url("http://example.org:1234")
qDebug() << "Host:" << url.host();
qDebug() << "Port:" << url.port();
As for your comment for avoiding the scheme usage in each url, you could use this:
url.setScheme("ftp");
or
url.setScheme("http");

Yes, you should use the QUrl::fromUserInput function to parse the string, and then the host and port methods of the QUrl object to get the QStrings that you want.
auto url{ QUrl::fromUserInput(address) };
auto host{ url.host() };
auto port{ QString::number(url.port()) };

Related

Qpid proton c++ - proton::make_work

I'm trying to add proton::work function (opening a new sender) inside the work queue of the proton::connection object. I have a pointer to the working queue, but my problem is how to bind the open_sender function correctly.
I'm aware of the real problem here : the parameter of the function :
sender open_sender(const std::string& addr);
As the string is passed by reference, I have to de-reference it. I'm ok with that, but how to do it with the proton tools ?
Here my line of code :
proton::work w = proton::make_work( &proton::connection::open_sender, &m_connection, p_url);
Note :
Of course I'm not using C++11 in my project, it would be too simple
to ask ;) !
Of course I cannot change to C++11
If you have a better idea on how to create a new sender in a multi-threaded program let me know.
Usually you will use the proton::open_sender API from within the handler for connection open or container start so you will not have to use proton::make_work in most cases. If you look at the Proton C++ examples, a good place to start is simple_send.cpp.
Abbreviated code might look like this:
class simple_send : public proton::messaging_handler {
private:
proton::sender sender;
const std::string url;
const std::string addr;
...
public:
simple_send(...) :
url(...),
addr(...)
{}
...
// This handler is called when the container starts
void on_container_start(proton::container &c) {
c.connect(url);
}
// This handler is called when the connection is open
void on_connection_open(proton::connection& c) {
sender = c.open_sender(addr);
}
...
}
int main() {
...
simple_send send(...);
proton::container(send).run();
...
}
There are other examples that come with Proton C++, that should help you figure out other ways to use Proton C++. See https://github.com/apache/qpid-proton/tree/master/examples/cpp.
There is also API documentation you can find at http://qpid.apache.org/releases/qpid-proton-0.20.0/proton/cpp/api/index.html (for the current release as of February 2018).

External vs internal declaration of QByteArray

I have currently some problems with the QSerialPort: When I am using the function from an example which looks like
QKeyEvent *e;
emit getData(e->text().toLocal8Bit());
connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray)));
void MainWindow::writeData(const QByteArray &data)
{
qDebug() << "Data is to write: " << data;
serial->write(data);
}
then the receiving device can work with the data. But when I change the function writeData() to
void MainWindow::writeData(const QByteArray &data)
{
QString a = "Q";
QByteArray b = a.toLocal8Bit();
serial->write(b);
}
the receiving device can not work with the received data. Where is the difference between those two approaches?
Update: I found out that apparently the data is only usefully transferred if I press Enter after typing the letters. Somehow the '\n' gets lost in the conversion from QString to QByteArray. How can I keep it?
you should add an enter to your Qstring like this
QString a = "Q\x00D";
In the example you have given, there is no "\n" in the QString! It is not getting lost, it is not there in the first place.
If a newline is necessary, then construct the String as QString a = "Q\n".
You can also construct the QByteArray directly from a character array rather than going through a char array -> QString -> QByteArrray conversion sequence, like so:
QByteArray b("Q\n");
EDIT: I realized that your contrived example where you are just sending the letter "Q" is probably a debug attempt, not your real code. In reality, you're getting data in as a QByteArray from some other signal that is emitting a QByteArray. That QByteArray that you are receiving must not include the newline character in it. If you are reading from a file or user input, then that is normal. Most readline-like functions strip off the trailing newline. If it is always necessary to have a newline, you can simply do something like this in your WriteData method:
void MainWindow::writeData(const QByteArray &data)
{
serial->write(data);
serial->write("\n");
}
If sometimes the passed-in QByteArray has a newline at the end and sometimes not, and your receiving device cannot handle redundant newlines, then you'd need to check whether data ends with a newline and only write the "\n" if it does not.
what if you make the QByteArray like this
QByteArray b(&a);

QT check if interface is real

I am tryng to get the mac adress using QT. Right now I am using this code:
QStringList Util::getMac(){
QStringList items;
foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
{
if (interface.flags().testFlag(QNetworkInterface::IsRunning))
foreach (QNetworkAddressEntry entry, interface.addressEntries())
{
if (interface.hardwareAddress() != "00:00:00:00:00:00" && entry.ip().toString().contains(".")){
items << interface.hardwareAddress();
}
}
}
return items;}
But the problem is that it also gives me mac adress of a hamachi interface. So is there any way to check if that interface is internet-accessible? Like that I would know that it is real and not virtual.
You could check the IP of the Interface via http://qt-project.org/doc/qt-4.8/qnetworkinterface.html#allAddresses and then see if it is an address that can connect to the internet

how to convert std::string to QString

I have a problem:
std::string str("character/test/raw");
qDebug() << QString::fromStdString(str);
and the output is:
"]AIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
I think the problem is in encoding but don't know how to fix it. Please help
string to const char*, then to qstring
std::string str("character/test/raw");
QString qstr(str.c_str());
qDebug() << qstr;
Is your QT compiled with STL compatible enabled option?
Maybe you can use fromUtf8 or one of other static functions of QString.

Qt + protobuf, types?

I would like to dip into Google's protocol buffers in Qt development, but I am having trouble figuring out how to incorporate them best.
Ultimately, I want to send with QUdpSocket and QTcpSocket using protocol buffers.
What is the best method for going between a protocol buffer message to sending the data over a socket (QByteArray) and then back again at the other side?
Creating a QByteArray from a protobuf object:
Person person; // a protobuf object
person.set_id(123);
person.set_name("Bob");
person.set_email("bob#example.com");
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
sendSerializedPersonOverQTcpSocket(byteArray);
Reading back a protobuf object from a QByteArray:
QByteArray byteArray = readSerializedPersonFromQTcpSocket();
Person person;
if (!person.ParseFromArray(byteArray, byteArray.size())) {
std::cerr << "Failed to parse person.pb." << std::endl;
}
Instead of:
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
you can also write:
QByteArray byteArray(person.SerializeAsString().c_str());
EDIT: Above two gives the same result, but I'm not sure wether it's correct. This one seems to work better:
QByteArray byteArray(QString::fromStdString(person.SerializeAsString()));
EDIT2: OK, now I know how it works: first two ways are wrong if there are \0 char in serialization - everything after it it's then lost. To correct it one can write:
QByteArray byteArray(person.SerializeAsString().c_str(), person.ByteSize());
Using the code below is really dangerous
std::ostringstream out;
person.SerializeToOstream(&out);
QByteArray byteArray(out.str().c_str());
sendSerializedPersonOverQTcpSocket(byteArray);
You can find a good explanation here In protobuf-c, can optional uint32 variable have value 0
A right way to create a QByteArray from a protobuf message is
QByteArray byteArray;
byteArray.resize(message.ByteSize());
message.SerializeToArray(byteArray.data(), byteArray.size());
#James: You can use ParseFromArray(), for example, as below: (Please note that ParseFromArray() is available only on proto-buf-lite versions of the libs).
void convertQByteArrayToUser(QByteArray& aByteArray)
{
com::your::name_space::User user;
if(!user.ParseFromArray(aByteArray.data(), aByteArray.size()))
{
//could not parse
}
else { //yayyyyy
if(user.has_userid())
{
//...
}
}
}