iostream and No_delay option - tcp

I am trying to disable the Nagle Algorithm using the answer for the same question: ASIO ip::tcp::iostream and TCP_NODELAY:
boost::asio::ip::tcp::iostream socketStream;
const boost::asio::ip::tcp::no_delay option( true );
socketStream.rdbuf()->set_option( option );
boost::asio::io_service io_service;
tcp::endpoint endpoint (tcp::v4 (), 6666);
tcp::acceptor acceptor (io_service, endpoint);
std::cout << "Waiting for connection.." << std::endl;
acceptor.accept (*socketStream.rdbuf ());
std::cout << "Connected!" << std::endl;
and when running the code this error appears:
set_option: Bad file descriptor
How can I solve this problem?

Where you set the option, the stream is still invalid (not open).
Wait until the socket is open, before setting the option:
Live On Coliru
#include <boost/asio.hpp>
#include <iostream>
static boost::asio::ip::tcp::no_delay const no_delay_option (true);
int main() {
using boost::asio::ip::tcp;
tcp::iostream socketStream;
boost::asio::io_service io_service;
tcp::endpoint endpoint (tcp::v4(), 6666);
tcp::acceptor acceptor (io_service, endpoint);
std::cout << "Waiting for connection.." << std::endl;
acceptor.accept (*socketStream.rdbuf ());
socketStream.rdbuf()->set_option(no_delay_option);
std::cout << "Connected!" << std::endl;
std::cout << socketStream.rdbuf() << "\n";
}
(We send main.cpp to port 6666 using netcat there)

Related

Make Peer-to-Peer communication on Qt Remote Objects

I want to make simple communication example on Qt Remote Objects. I want to make the communication peer-to-peer, therefore I'm trying to merge both Source and Replica of the same remote object functionality in one application (REPC_MERGED tool used to generate Source and Replica base classes).
#include <QtCore/QCoreApplication>
#include "MyPeerHost.h"
#include "Client.h"
#include <QDebug>
static QString peer_node_name(int number)
{
QString ret = QString("peer_%1").arg(number);
return ret;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyPeerHost peerHost; // just inherits auto-generated MyPeerSimpleSource
QUrl thisAddress = "local:" + peer_node_name(0);
QRemoteObjectHost sourceNode(thisAddress);
if(sourceNode.enableRemoting(&peerHost))
{
qInfo() << "Source remoting enabled successfully" << thisAddress;
QUrl remoteAddress = "local:" + peer_node_name(1);
QSharedPointer<MyPeerReplica> replica;
QRemoteObjectNode replicaNode;
if(replicaNode.connectToNode(remoteAddress))
{
qInfo() << "Replica connected to the address" << remoteAddress << "successfully";
replica.reset(replicaNode.acquire<MyPeerReplica>());
QString sourceClassName = peerHost.staticMetaObject.className();
qDebug() << "Replica wait for Source" << sourceClassName << "...";
if(replica->waitForSource(1000))
{
qInfo() << "Replica object completely initialized";
Client client;
client.setReplicaObject(replica);
client.sendMessage("AAA");
}
else
{
qCritical() << "Replica wait for Source" << sourceClassName << "FAILED" << replicaNode.lastError();
}
}
else
{
qCritical() << "Replica connect to the address" << remoteAddress << "FAILED" << replicaNode.lastError();
}
}
else
{
qCritical() << "Source remoting enable FAILED" << sourceNode.lastError();
}
return a.exec();
}
Application output:
Source remoting enabled successfully QUrl("local:peer_0")
Replica connected to the address QUrl("local:peer_1") successfully
Replica wait for Source "MyPeerHost" ...
Replica wait for Source "MyPeerHost" FAILED QRemoteObjectNode::NoError
As you see, replicaNode successfully connected to the non-existent node QUrl("local:peer_1").
What I am doing wrong?
You don't have valid Qt code.
Qt relies on an event loop to handle asynchronous behavior, which is started by the a.exec() at the end of your main() routine. Qt Remote Objects, in turn, relies on the event loop for all of its communication.
In your code, you create your objects on the stack, but in code blocks that go out of scope before you start the event loop. They will therefore be destructed before the event loop is kicked off.
I'd recommend starting with some of the examples, make sure they work, then grow what you are trying to do from there.

Can I query the list of variables and types

Can I use twincat-ads to query a Beckhoff PLC for the variables (and their types) that are exposed on ADS.
Yes you can.
This example comes directly from the Beckhoff ads documentation which you should study a bit in order to understand the basics of the ads protocol.
/// <summary>
/// Defines the entry point of the application.
/// </summary>
/// <param name="args">The arguments.</param>
static void Main(string[] args)
{
    Console.WriteLine("");
    Console.WriteLine("Press [Enter] for start:");
    Console.ReadLine();
    // Parse the command-line arguments
    AmsAddress address = ArgParser.Parse(args);
    using (TcAdsClient client = new TcAdsClient())
    {
    // Connect the AdsClient to the device target.
    client.Connect(address);
    // Load symbolic information
    ISymbolLoader loader = SymbolLoaderFactory.Create(client, SymbolLoaderSettings.Default);
    ReadOnlySymbolCollection allSymbols = loader.Symbols;
    ISymbol bVar1 = allSymbols["GVL.bVar1"];
    ISymbol bVar2 = allSymbols["GVL.iCount"];
    ISymbol projectName = allSymbols["TwinCAT_SystemInfoVarList._AppInfo.ProjectName"];
    SymbolCollection symbols = new SymbolCollection() {bVar1, bVar2, projectName};
    // Sum Command Read
    SumSymbolRead readCommand = new SumSymbolRead(client,symbols);
    object[] values = readCommand.Read();
    for (int i = 0; i < symbols.Count; i++)
    {
        Console.WriteLine("Symbol: {0} (Value: {1}, Type: {2})",symbols[i].InstancePath,values[i].ToString(),values[i].GetType().Name);
    }
    // Sum Command Write
    SumSymbolWrite writeCommand = new SumSymbolWrite(client,symbols);
    object[] writeValues = new object[] {true, (short) 42, "MyNewProjectName"};
    writeCommand.Write(writeValues);
    }
    Console.WriteLine("");
    Console.WriteLine("Press [Enter] for leave:");
    Console.ReadLine();
}
In C++ you need to use the AdsSyncReadReq function:
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <assert.h>
// ADS headers for TwinCAT 3
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"
void main()
{
long nErr, nPort;
char *pchSymbols = NULL;
UINT uiIndex;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
AdsSymbolUploadInfo tAdsSymbolUploadInfo;
PAdsSymbolEntry pAdsSymbolEntry;
// Open communication port on the ADS router
nPort = AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
// Select Port: TwinCAT 3 PLC1 = 851
pAddr->port = 851;
// Read the length of the variable declaration
nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOADINFO, 0x0, sizeof(tAdsSymbolUploadInfo), &tAdsSymbolUploadInfo);
if (nErr) cerr << "Error: AdsSyncReadReq: " << nErr << '\n';
pchSymbols = new char[tAdsSymbolUploadInfo.nSymSize];
assert(pchSymbols);
// Read information about the PLC variables
nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOAD, 0, tAdsSymbolUploadInfo.nSymSize, pchSymbols);
if (nErr) cerr << "Error: AdsSyncReadReq: " << nErr << '\n';
// Output information about the PLC variables
pAdsSymbolEntry = (PAdsSymbolEntry)pchSymbols;
for (uiIndex = 0; uiIndex < tAdsSymbolUploadInfo.nSymbols; uiIndex++)
{
cout << PADSSYMBOLNAME(pAdsSymbolEntry) << "\t\t"
<< pAdsSymbolEntry->iGroup << '\t'
<< pAdsSymbolEntry->iOffs << '\t'
<< pAdsSymbolEntry->size << '\t'
<< PADSSYMBOLTYPE(pAdsSymbolEntry) << '\t'
<< PADSSYMBOLCOMMENT(pAdsSymbolEntry) << '\n';
pAdsSymbolEntry = PADSNEXTSYMBOLENTRY(pAdsSymbolEntry); cout.flush();
}
getch();
// Close communication port
nErr = AdsPortClose();
if (nErr) cerr << "Fehler: AdsPortClose: " << nErr << '\n';
// Release memory
if (pchSymbols) delete(pchSymbols);
}
For more info:
https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_ads_intro/9007199370899851.html&id=5869483416056481636

Receipt printer feeds paper instead of printing text

I am working on test application for printing in Ubuntu 14.04.3 LTS with CUPS 1.7.2 and Qt 5.5.1 Opensource 64bit. I've added printer with its driver in CUPS and test page is printed ok. Now, my app consists of QTextEdit and QPushButton, whose pressed() signal triggers following slot:
void UeCentralWidget::ueSendTextToPrinter()
{
// QStringList availablePrintersNames=QPrinterInfo::availablePrinterNames();
// for(int indexPrinterName=0; indexPrinterName<availablePrintersNames.size(); indexPrinterName++)
// {
// qDebug() << Q_FUNC_INFO
// << availablePrintersNames.at(indexPrinterName);
// } // for
qDebug() << Q_FUNC_INFO
<< "Text to print: "
<< this->uePrinterTextEditor()->document()->toPlainText();
QList<QPrinterInfo> availablePrinters=QPrinterInfo::availablePrinters();
for(int indexPrinter=0; indexPrinter<availablePrinters.size(); indexPrinter++)
{
// qDebug() << Q_FUNC_INFO
// << availablePrinters.at(indexPrinter).makeAndModel();
if(availablePrinters.at(indexPrinter).makeAndModel().contains("POS58"))
{
qDebug() << Q_FUNC_INFO
<< "Printer found";
QPrinter printer(availablePrinters.at(indexPrinter));
qDebug() << Q_FUNC_INFO
<< printer.pageLayout().fullRect();
QPainter printerPainter(&printer);
qDebug() << Q_FUNC_INFO
<< printerPainter.fontInfo().family()
<< printerPainter.fontInfo().pixelSize()
<< printerPainter.fontInfo().pointSize();
if(printerPainter.begin(&printer))
{
printerPainter.drawText(100,
100,
this->uePrinterTextEditor()->document()->toPlainText());
}
printerPainter.end();
} // if
} // for
}
When this slot executes, printer job is added to CUPS queue, which means printer is found, however, printer just feeds printer and no text is printed. What am I still missing?
You don't need the printerPainter.begin(&printer) or the printerPainter.end().
I don't know why that fixes it for you, but if I was to guess it might be because explicitly calling printerPainter.end() prematurely completes the paint operation before the drawing is actually done.

App crashes when I try to read QString from socket

I am trying to develop a Qt program using sockets for client and server communication. I need help with figuring out why my server crashes when the client connects and the server tries to get a QString?
I have this code on the server side:
void Client::onReadyRead() {
qDebug() << "On ready read!";
QDataStream in(mSocket);
in.setVersion(QDataStream::Qt_4_0);
for (;;) {
if(!mBlockSize) {
if (mSocket->bytesAvailable() < sizeof(quint16)) break;
in >> mBlockSize;
}
if(mSocket->bytesAvailable() < mBlockSize) break;
qDebug() << "Package was recieved!";
qDebug() << "Block size: " << mBlockSize;
if(Table::INVALID_ID == mUser.id()) {
QString authStr;
in >> authStr;
qDebug() << "Recieved account data: " << authStr;
}
mBlockSize = 0;
}
}
And on the client side:
void Client::onConnected()
{
qDebug() << "Connected!";
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
//Reserve 2 bytes
out << (quint16)0 << mEmail << "|" << mPassword;
//Back to the beginning
out.device()->seek(0);
//Write a block size
out << (quint16)(block.size() - sizeof(quint16));
mSocket->write(block);
}

QMediaPlayer : media stays in UnknownMediaStatus

I created a QMediaPlayer, passed video address to it and it won't play. I checked the mediaStatus and player state, they all stays 0 all the time. The basic idea is:
QMediaPlayer player = new QMediaPlayer();
cout << player.mediaStatus(); // should print 1: NoMedia but is 0: UnknownMediaStatus
player.setVideoOutput(some_constructed_video_widget);
cout << player.mediaStatus(); // should print 1: NoMedia but is 0: UnknownMediaStatus
player.setMedia(QUrl::fromLocalFile("path/to/test/video/test.mp4"));
cout << player.mediaStatus(); // should print 2: LoadingMedia but is 0: UnknownMediaStatus
player.play();
cout << player.mediaStatus(); // should print 3: LoadedMedia but is 0: UnknownMediaStatus
// and of course, no video gets played
The mediaStatus is simply a enum: MediaStatus { UnknownMediaStatus, NoMedia, LoadingMedia, LoadedMedia, ..., InvalidMedia }
The questions are:
What may be causing this problem and how to fix that?
What are all the cases that a QMediaPlayer::mediaStatus() will return an QMediaPlayer::UnknownMediaStatus (please be conclusive)?
Edit with more information: The following is the output I get for the following code. Anyone has any idea what the error message means and how to fix that?
code:
int main(int argc, char *argv[])
{
QMediaPlayer * temp = new QMediaPlayer(0, QMediaPlayer::VideoSurface);
std::cout << "Constructed: " << temp->mediaStatus() << std::endl;
temp->setMedia(QUrl::fromLocalFile("path/to/video/test.mp4"));
std::cout << "SetMedia: " << temp->mediaStatus() << std::endl;
temp->play();
std::cout << "Play: " << temp->mediaStatus() << std::endl;
-> debug breakpoint here
......
}
output:
defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"
Constructed: 0
SetMedia: 0
Play: 0
I am using Mac 10.9 and Qt 5.3.0, but I do not think the mac/qt version matters for this problem.

Resources