Basic Qt tcp-server application only show selected clients messages - qt

I am developing a simple tcp server with qt. There is no problem with that. But the problem is, i have listed every connected client in a listbox and i want to see the incoming data only from the selected client from the listbox but i can only see the last connected client's messages.
here is the code,
this is the constructor part
server = new QTcpServer();
client = new QTcpSocket();
connect(server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
server->listen(QHostAddress::Any, ui->txtPort->text().toInt(bool(),10));
if(server->isListening())
{
ui->statusBar->showMessage("Server Started..");
}
else
{
ui->statusBar->showMessage("Server Not Started..");
}
connect(client,SIGNAL(disconnected()),this,SLOT(client_disconnected()));
connect(ui->listWidget,SIGNAL(clicked(QModelIndex)),this,SLOT(selected_client()));
here is acceptConnection() part
client = server->nextPendingConnection();
ui->listWidget->insertItem(client_count,client->peerAddress().toString());
client_count++;
and this is the listWidget item's selected item event
ui->txtRead->clear();
selected_client_index = ui->listWidget->currentIndex().row();
connect(client, SIGNAL(readyRead()),this, SLOT(startRead()));
and lastly the startRead() part
char buffer[1024] = {0};
client->read(buffer, client->bytesAvailable());
qDebug() << buffer;
ui->txtRead->insertPlainText(buffer);
How can i select the specific client and show its messages ?
Thanks in advance.

You should not use client in startRead, but some selectedClient, that You remembers in selected_client() SLOT.
As for now, when You use client = server->nextPendingConnection(), You are losing any previous clients. You should save them into some QList<QTcpSocket*>.

Related

Retrieve data from QDBusMessage in Qt

I'm developing an app which have to implement a WiFi connection mechanism (it'll be a fullscreen touchscreen app). To do that I'm using the DBus to communicate with Network Manager. I managed to successfully make it scan access points and list them in the QTableView. Next thing will be to connect to the chosen wifi network. First thing I do when trying to connect is checking if there is an existing connection to that access point already in the system so I do this:
settings = new QDBusInterface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings", "org.freedesktop.NetworkManager.Settings", dbusConnection, this);
QDBusMessage msg = settings->call("ListConnections");
QDBusArgument arg = msg.arguments().at(0).value<QDBusArgument>();
QList<QDBusObjectPath> pathsList = qdbus_cast<QList<QDBusObjectPath>>(arg);
foreach (QDBusObjectPath p, pathsList) {
QDBusInterface *conn = new QDBusInterface("org.freedesktop.NetworkManager", p.path(), "org.freedesktop.NetworkManager.Settings.Connection", dbusConnection);
QDBusMessage msg = conn->call("GetSettings");
qDebug() << "Reply: " << msg;
}
I receive the message and can read it with qDebug(). The message is in d-bus format: a{sa{sv}} as the documentation for Network Manager says. And I have problem to parse it to any usable form. From what I understand, the equivalent Qt classes I should put the data to are:
QList<QMap<QString, QMap<QString, QVariant>>>
And I think I should do it with the QDBusArgument class but can't figure out how exactly it should be done. Can someone tell me what is the best way to do this?
Thanks.
I managed to solve my problem, it turned out to be quite easy. I created the map object and used >> operator:
QDBusArgument arg = args.at(0).value<QDBusArgument>();
QMap<QString, QMap<QString, QVariant>> map;
arg >> map;

Asynchronous hive query execution : OperationHandle gets cleaned up at server side as soon as the query initiator client disconnects

Is it possible to execute a query asynchronously in hive server?
For eg, How can I /Is it possible to do something like this from the client-
QueryHandle handle = executeAsyncQuery(hiveQuery);
Status status = handle.checkStatus();
if(status.isCompleted()) {
QueryResult result = handle.fetchResult();
}
I also had a look at How do I make an async call to Hive in Java?. But did not help. The answers were mostly around the thrift clients taking a callback argument.
Any help would be appreciated. Thanks!
[EDIT 1]
I went through the HiveConnection.java in hive-jdbc. hive-jdbc by default uses the async thrift APIs. Hence it submits a query and polls for result sets (look at HiveStatement.java). Now i am able to write a piece of code which is purely non blocking. But the problem is as soon as the client disconnect the foot print about the query is lost.
Client 1
final TCLIService.Client client = new TCLIService.Client(createBinaryTransport(host, port, loginTimeout, sessConf, false)); // from HiveConnection.java
TSessionHandle sessionHandle = openSession(client) // from HiveConnection.java
TExecuteStatementReq execReq = new TExecuteStatementReq(sessionHandle, sql);
execReq.setRunAsync(true);
execReq.setConfOverlay(sessConf);
final TGetOperationStatusReq handle = client.ExecuteStatement(execReq)
writeHandleToFile("~/handle", handle)
Client 2
final TGetOperationStatusReq handle = readHandleFromFile("~/handle")
final TCLIService.Client client = new TCLIService.Client(createBinaryTransport(host, port, loginTimeout, sessConf, false));
while (true) {
System.out.println(client.GetOperationStatus(handle).getOperationState());
Thread.sleep(1000);
}
Client 2 keeps printing FINISHED_STATE as long as Client 1 is alive. But if client 1 process completes or gets killed, client 2 starts printing null which means hiveserver2 is cleaning up the resources as soon as a client disconnects.
Is it possible to configure hiveserver2 to configure this clean up process based on time or something?
Thanks!
Did some research and figured out that this happens only with binary transport (tcp)
#Override
public void deleteContext(ServerContext serverContext,
TProtocol input, TProtocol output) {
Metrics metrics = MetricsFactory.getInstance();
if (metrics != null) {
try {
metrics.decrementCounter(MetricsConstant.OPEN_CONNECTIONS);
} catch (Exception e) {
LOG.warn("Error Reporting JDO operation to Metrics system", e);
}
}
ThriftCLIServerContext context = (ThriftCLIServerContext) serverContext;
SessionHandle sessionHandle = context.getSessionHandle();
if (sessionHandle != null) {
LOG.info("Session disconnected without closing properly, close it now");
try {
cliService.closeSession(sessionHandle);
} catch (HiveSQLException e) {
LOG.warn("Failed to close session: " + e, e);
}
}
}
The above stub (from ThriftBinaryCLIService) gets executed through this piece of code from TThreadPoolServer which is used by ThriftBinaryCLIService.
eventHandler.deleteContext(connectionContext, inputProtocol,
outputProtocol);
Apparently http transport (ThriftHttpCLIService) has a different strategy of cleaning up operation handles (not greedy like tcp)
Will check with hive community on this to understand a bit more and see if there is an issue addressing this already.

Scanning the serial port periodically to see if the device is connected in QT, QSerialPort

I am trying to scan my serial ports periodically to see if my device is connected or not. Here is what I have done and it works well. I would like to see if there is a better and optimized way to do so.
I created the following timer in my constructor to check the serial port frequently. I made a method (scanSerialPorts()) and call it every 1 second.
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(scanSerialPorts()));
timer->start(1000);
This is my scanSerialPorts() implementation:
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
currentPortName = info.systemLocation();
}
if (currentPortName == "My Desired PortName" ) {
updateSettings();
if ( !serial->isOpen()){
qDebug() << "Serial Not Open";
openSerialPort();
}
} else
{
serial->close();
}
updateSettings(); // Fills up the serial port parameters.
openSerialPort(); //Opens up the serial port.
I used QT examples to write this. Please let me know what you think and how I can make it better.
As it is, you only scan the last port, since the rest of the code is outside the foreachloop;
You close the other (probably not opened) ports instead of the one you're opening
Most probably, availablePorts won't change during execution, so you could move it outside of the scan function to save some processing time in the timer. The same for updateSettings().

Asp .net Session is timeout and all data wasn't saved , any idea?

I created an web application where a lot of words was needed in the application which take a lot of time and thinking when u need to write it.
Let's suppose the session timeout after 30 minutes,i started writing a lot of words and while thinking and writing the session timeout and redirect to the login page and all written data is lost.
Any idea for this problem except extending session timeout period ???
Currently your session is created and managed as In-Process mode and in this mode you cannot recover session state once it reaches timeout stage. You may set SQL Server Mode and configure your application for SQL Server Mode so your data will be persisted into Sql Server database.
Profile Properties is an alternate to save the state.
You can use some ajax function that regularly "calls home" (executes some dummy code on the server). This will keep the session alive as long as that user has this page open.
You might need to explicitly use the Session in that callback, such as
Session["LastAccess"] = DateTime.Now;
just to keep it alive.
If you execute this call every 15 minutes, the session will not time out and the load on the server is minimal.
Use asynchronous programming model which allowing some portion of code to be executed on a separate threads.
There are three style of Programming with APM
Wait Until Done Model
Polling Model
Callback Model
Based on your requirement and result you can choose the model which is more appropriate.
For instance, let us say you can to read the file and wait until done and sample code is
byte[] buffer = new byte[100];
string filename =
string.Concat(Environment.SystemDirectory, "\\mfc71.pdb");
FileStream strm = new FileStream(filename,
FileMode.Open, FileAccess.Read, FileShare.Read, 1024,
FileOptions.Asynchronous);
// Make the asynchronous call
strm.Read(buffer, 0, buffer.Length);
IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
// Do some work here while you wait
// Calling EndRead will block until the Async work is complete
int numBytes = strm.EndRead(result);
// Don't forget to close the stream
strm.Close();
Console.WriteLine("Read {0} Bytes", numBytes);
Console.WriteLine(BitConverter.ToString(buffer));
But creating your threads are not necessary or suggesting, .NET supports a built in thread pool that can be used in many situation where you thinking to create your own threads. Sample code
static void WorkWithParameter(object o)
{
string info = (string) o;
for (int x = 0; x < 10; ++x)
{
Console.WriteLine("{0}: {1}", info,
Thread.CurrentThread.ManagedThreadId);
// Slow down thread and let other threads work
Thread.Sleep(10);
}
}
Instead of creating a new thread and controlling it, we use the ThreadPool to this work by using its QueueWorkItem method
WaitCallback workItem = new WaitCallback(WorkWithParameter));
if (!ThreadPool.QueueUserWorkItem(workItem, "ThreadPooled"))
{
Console.WriteLine("Could not queue item");
}

QDialog::accept quits Main Application

I have a ClientSocket Class which is a TcpSocket in a certain state of conversation I need to ask the user to enter a Communication password. So I've created a Dialog DG::ChallangeDialog . in DG::ChallangeDialogs ctor I've
ui->setupUi(this);
QPushButton* okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
if(okButton != 0x0){
okButton->setText("Challange");
}
QObject::connect(this, SIGNAL(accepted()), this, SLOT(acceptedSlot()));
acceptedSlot again emits a signal challanged(QString)
void ChallangeDialog::acceptedSlot(){
QString text = ui->passBox->text();
emit challanged(text);
}
in ClientSocket I do
case Hallo:{
if(m->message().startsWith("welcome")){
DG::ChallangeDialog* dlg = new DG::ChallangeDialog;
dlg->setModal(true);
connect(dlg, SIGNAL(challanged(QString)), this, SLOT(challanged(QString)));
dlg->exec();
/*
DG::MessagePacket* res = new DG::MessagePacket((int)Hallo);
res->setMessage("challange");
send(res);
state = Challange;
*/
}
}break;
In ClientSocket::challange slot I send a Message challange (text) over the socket and store the password.
and I expect the Dialog to hide there and the normal socket conversation to continue. and after the Dialog is accepted or rejected the main application quits (It quits it doesn't crash). Why ?
My Application has no Other Widgets. I just works like an QCoreApplication. But still I've used QApplication cause I've some GUI Needs.
Is this the only window that is shown at this time? If so, I would guess that your QApplication instance is set to quit when the last window is closed. It is true by default.
If this is the case, you should explicitly set this to false before showing any windows.

Resources