not able to start qlocalserver - qt

I use Qlocalsocket in my IPC solution and I am able to start the server and accept connections from QLocalSocket clients and communicate well, no prob in that.
but my problem happens when I kill the process of the server , I can't make QLocalServer listen on the same place again, I must change the service name to be able to start it again, which could not be possible at runtime environment.
so how to make the previous process to release that name?
here is how I start the server:
m_server = new QLocalServer(this);
if (!m_server->listen("serviceUniqueName")) {
qDebug() << "Not able to start the Server";
return;
}

As Amartel pointed out, if the server dies, you need to delete the socket file.
The best way to do is to call bool QLocalServer::removeServer ( const QString & name ):
m_server = new QLocalServer(this);
QString serverName("serviceUniqueName");
QLocalServer::removeServer(serverName);
if (!m_server->listen(serverName)) {
qDebug() << "Not able to start the Server";
return;
}
This way your call to listen will never fail.

Qt help:
On Unix if the server crashes without closing listen will fail with
AddressInUseError. To create a new server the file should be removed.
On Windows two local servers can listen to the same pipe at the same
time, but any connections will go to one of the server.
So, if you are using *nix, you should remove file "/tmp/socket_name".

Related

Qt unix domain socket server side reading

I am using Qt for unix domain socket and I have a question:
I want the server side read the message sent from the client side right after the connection established, below are my codes
if (!server->listen("mySocket2")) {
//lisetn for new connection
close();
return;
}
connect(server, &QLocalServer::newConnection, this, &MainWindow::readData);
And in the readData function
QLocalSocket *clientConnection = server->nextPendingConnection();
connect(clientConnection, &QLocalSocket::disconnected,
clientConnection, &QLocalSocket::deleteLater);
connect(clientConnection,&QLocalSocket::readyRead,
this,&MainWindow::readyReadData);
In the readyReadData function
QByteArray block;
block=clientConnection->readAll();
qDebug()<<block;
clientConnection->disconnectFromServer();
but the app always crashed, can you plz advise me on that?
I don't see any condition handling for when there are no pending connections. This case will cause nextPendingConnection() to return a nullptr (actually, just a zero), which may or may not cause the signal/slot connections to fail.

QTcpSocket KeepAliveOption on server side

I would like to set QTcpSocket::KeepAliveOption on the server side, so that the connection gets automatically disconnected when the network connection is lost for some time.
However, the documentation says:
On Windows Runtime, QAbstractSocket::KeepAliveOption must be set before the socket is connected.
On a client, you would just create the socket, set the option, then connect it.
On the server side, you do not create the sockets, they are created and returned buy QTcpServer::nextPendingConnection(). These are already connected.
So am I basically stuck, and is the only viable option to implement "heartbeats" myself?
EDIT
I have created a QTcpServer subclass as suggested by talamaki for setting the flag on incoming connection sockets:
class CustomTcpServer : public QTcpServer
{
Q_OBJECT
public:
CustomTcpServer(QObject * parent = 0) : QTcpServer(parent) { }
void incomingConnection(qintptr socketDescriptor)
{
QTcpSocket *socket = new QTcpSocket(this);
socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
socket->setSocketDescriptor(socketDescriptor);
addPendingConnection(socket);
}
};
Then, i have set
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters\KeepAliveTime
To a DWORD value of 30000 (thirty seconds)
And rebooted the system to be sure it is used by the system
But, I still get no disconnected signal after several minutes, after having unplugged the ethernet cable of the remote client.
How to make the KeepAlive feature work?
Thanks
You should be able override QTcpServer::incomingConnection and create QTcpSocket yourself instead of letting the framework do it.
On Windows, AFAIK there are three parameters that govern the timeout of a TCP connection. You have set the KeepAliveTime, which is the time until an idle connection will be starting to send keep-alive segments (the connection must be idle, no segments have been sent, no Acks received). Then there is the number of keep-alives that need to be unanswered to determine that it is dead, which is TcpMaxDataRetransmissions. Finally, the is the time between the keep-alive segments which is KeepAliveInterval. Check with Wireshark, if empty TCP segments are being sent (which are the Keep-Alives). Some versions of Windows might misbehave, too and ignore some of the settings.
Usually Servers re-starts the Listenning after a elapsed time without traffic. After close en re-open , new connections will arrive.
ALSO Client and Server can specify a test protocol like PING - PONG message on interval of X seconds, minutes, etc
In server side, when missing pings after X seconds, maybe indicate to restart the server.
Best regards!

Cannot reconnect to serial port that was previously opened in the same TCL script

I have been working towards automating hardware testing using TCL, where the hardware is connected to a serial port. The current script can connect to the serial port the first time through, and disconnect at the end. However, it cannot reconnect to the serial port again unless the application is closed and reopened.
The code to connect to the serial port is:
if { [catch {spawn -open [open $port r+] } results] } {
puts $results
puts "Could not connect to port.\n"
return -1 }
with the successful return statement being return $spawn_id
The code that is supposed to close the connection to the serial port is:
if {[catch {close -i $handle} results]} {
puts "$results"
puts "Failed to Close Session $handle\n\r"
return -1 }
#waits for handle to be properly closed
exp_wait
where $handle is the spawn_id returned by the open procedure.
I wrote a short test script to demonstrate how I am trying to use this:
source console.tcl
puts "available COM ports are: [console::availableSerial]"
set handle [console::openSession COM6 BARE>]
if {[catch {console::closeSession $handle} results]} {
puts $results }
if {[catch {console::openSession COM6 BARE>} results]} {
puts $results }
where 'console::' is the namespace of the open and close procedures in question
I have tried playing around with some of the fconfigure parameters, such as enabling and disabling blocking, but to no avail.
The error message displayed by TCL is `couldn't open serial "COM6": permission denied' , suggesting the port is not being closed properly. The book 'Exploring Expect' does not have much information specific to this, so I was hoping someone here would be able to provide some insight into what I am doing wrong. I am using 32-bit ActiveState ActiveTCL 8.6.3.1 and my shell is Tclsh36
Any feedback will be appreciated. Thanks.
The problem here stems from using proc to deal with a spawned connection. If a connection is spawned in a procedure (call it foo1), than another procedure (call if foo2) cannot immediately interact with it. For this to work, the spawn_id must be returned from foo1 and passed in as a parameter to foo2. This does not only affect sending information to the spawned connection, but also receiving information from that connection.
In my case, I called close -i $handle, which was correct, but then simply called exp_wait. the exp_wait was not called using the spawn_id passed in, so was not waiting for the correct response.
The fix was to simply replace exp_wait with exp_wait -i $handle

QTcpSocket will cause handles increase in windows

I use qt4.8.5 and windows.
I use QTcpSocket to connect a server.
If the server doesn't open, then I will try to connect it.
My way is:
sock = new QTcpSocket(this);
sock->connectToHost("127.0.0.1", 1234);
connect(sock, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(error(QAbstractSocket::SocketError)));
I will get the error() signal.
sock->close();
sock->deletelater();
I use a timer to try to connect, and it did call the error() to delete the sock.
But I found that the handles increase in the Task Manager. Does it have memory leak? but I have close the sock and use deletelater().
What's more, the socket object not run in the main thread.
If any one know the reason cause the handles increase, please tell me.
Thanks!

H2 Database Server to serve TCP clients from connection pool

I have a H2 server that I start from console. The client from different machine accesses the server and calls a function alias (registered at the database). The problem is, this function is called more than a million times. So, in this case, the connection timesout but then I solved it with changing the client connection string to have AUTORECONNECT=TRUE. This solves the problem but adds a reconnection time delay (which I want to avoid).
Is there any flag/command that we can use to specify with Server to dedicate X amount of connections?
Also, I looked into the possibility of starting the server from within Application. Like,
JdbcConnectionPool cp = JdbcConnectionPool.create(
"jdbc:h2:tcp://IPADDRESS:9092/~/test", "sa", "");
cp.setMaxConnections(MAX_CONN_IN_POOL);
// start the TCP Server
Server server = Server.createTcpServer().start();
Connection conn = cp.getConnection();
Statement stat = conn.createStatement();
stat.execute("SELECT myFunctionAlias(arg)");
cp.dispose();
server.stop();
The above sample code does start the server and will only run once. I want the server to be open and keep listening to clients, and serve them from the connection pool. Any pointers?
You should start the server in AUTO_SERVER mode, this way a leader election algorithm will elect a leader who will read the database file and open a TCP server for all other clients.
Thsi way the server will be really fast to read the file while other clients will be as fast as the network is.
This is transparent to the user as long as you use the same connection string.
Connection connection;
String dataBaseString = "jdbc:h2:/path/to/db/" + File.separator + "db;create=true;AUTO_SERVER=TRUE;AUTO_RECONNECT=TRUE";
try
{
Class.forName("org.h2.Driver");
log.info("getConnection(), driver found");
}
catch (java.lang.ClassNotFoundException e)
{
log.error("getConnection(), ClassNotFoundException: " + e.getMessage(), e);
Main.quit();
}
try
{
connection = DriverManager.getConnection(dataBaseString);
}

Resources