View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0000976 | SkyChart | 1-Software | public | 12-04-15 19:18 | 13-05-06 14:33 |
| Reporter | JS | Assigned To | Patrick Chevalley | ||
| Priority | normal | Severity | minor | Reproducibility | N/A |
| Status | closed | Resolution | fixed | ||
| Platform | x86 | OS | Mac OS | OS Version | 10.5 |
| Product Version | 3.6 | ||||
| Target Version | 3.8 | Fixed in Version | 3.7 SVN | ||
| Summary | 0000976: TCP Server spec | ||||
| Description | Hello, I'm currently trying to write a program whose goal is to send pointing commands to Skychart using the TCP interface. The TCP server appears to periodically send a "." char on the socket (port 3292), which i receive correctly. But it does not seem to respond to the commands i send on the same socket. When i talk to the server using a basic telnet client, everything goes fine: the server acknowledges my requests by sending back a "OK" message. This does not seem to appear when the requests are sent by my program. So my question is - when and why are the "." emitted by the TCP server - is the exact behavior of the TCP server documented somewhere Thanks JS | ||||
| Tags | No tags attached. | ||||
|
|
The "." are send to check that the client is still connected and maintain the status in the server information window: http://www.ap-i.net/skychart/en/documentation/menuview#server_information If you not need that you can suppress them by unchecking "Client Connection Keep Alive" in the System setting: http://www.ap-i.net/skychart/en/documentation/system#server An important point is to purge the receive buffer before to send a new command. This is what do the function clearInput() in the Java example client: http://skychart.svn.sourceforge.net/viewvc/skychart/trunk/skychart/sample_client/java/CdcClient.java?view=markup See also my response to this issue: http://www.ap-i.net/mantis/view.php?id=964#c2013 |
|
|
Ok, thanks ! Will have a look at the Java example. Btw, is there a way to force CdC to log informations about the msgs received by the server (if launched from the command line) (some kind of "verbose mode") ? Jocelyn |
|
|
Unfortunately there is no verbose mode at the moment except by recompiling the program with a specific switch. I look to add this option. |
|
|
I finally managed to have this running. In case anyone could find this useful, here's a Qt/C++ class doing the job... ---- tcpClient.h : #ifndef _tcpClient_h #define _tcpClient_h #include <QTcpSocket> #include <QHostAddress> class TcpClient : public QObject { Q_OBJECT public: TcpClient(QHostAddress host, int port); bool isConnected() { return is_connected; } QString readLine(); void sendData(const QString &msg); signals: void receivedData(const QString &msg); void errorMsg(const QString &msg); void connected(); void disconnected(); private slots: void readData(); void error(QAbstractSocket::SocketError); void set_connected(); void set_disconnected(); public slots: void connect(); void disconnect(); void quitting(); private: void clearInput(); QTcpSocket *tcpSocket; bool is_connected; QHostAddress host; int port; }; #endif ---------------- ---- tcpClient.cpp #include "tcpClient.h" TcpClient::TcpClient(QHostAddress host_, int port_) { tcpSocket = new QTcpSocket(); QObject::connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readData())); QObject::connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); QObject::connect(tcpSocket, SIGNAL(connected()), this, SLOT(set_connected())); QObject::connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(set_disconnected())); host = host_; port = port_; connect(); } void TcpClient::connect() { if ( ! isConnected() ) tcpSocket->connectToHost(host, port); } void TcpClient::disconnect() { if ( isConnected() ) sendData("quit"); tcpSocket->disconnectFromHost(); } void TcpClient::readData() { QTextStream in(tcpSocket); if ( tcpSocket->canReadLine() ) { QString s = tcpSocket->readLine(); emit receivedData(s); } } void TcpClient::clearInput() { QTextStream in(tcpSocket); while ( tcpSocket->canReadLine() ) { QString s = tcpSocket->readLine(); } } void TcpClient::sendData(const QString &msg) { QTextStream out(tcpSocket); QString data = msg + "\r\n"; out << data << endl; } void TcpClient::set_connected() { is_connected = true; emit connected(); } void TcpClient::set_disconnected() { is_connected = false; emit disconnected(); } void TcpClient::error(QAbstractSocket::SocketError socketError) { switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: emit errorMsg("Host not found"); break; case QAbstractSocket::ConnectionRefusedError: emit errorMsg("Connection refused by peer"); break; default: emit errorMsg(tcpSocket->errorString()); break; } } void TcpClient::quitting() { if ( isConnected() ) { disconnect(); } } ---------- ... and a small example application using it : ----- cdcClient.h #ifndef _cdcClient_h #define _cdcClient_h #include "tcpClient.h" #include <QDialog> class QTextEdit; class QPushButton; class QLineEdit; class QLabel; class CdcClient : public QDialog { Q_OBJECT public: CdcClient(QWidget *parent = 0); ~CdcClient() { quitting(); } private slots: void sendCmd(); void displayMsg(const QString &); void displayError(const QString &); void set_connected(); void set_disconnected(); public slots: void quitting(); private: TcpClient *client; QPushButton *sendButton; QPushButton *connectButton; QPushButton *disconnectButton; QLineEdit *cmdTxt; QTextEdit *display; QLabel *status; }; #endif --------- ------ cdcClient.cpp #include "cdcClient.h" #include <QtGui> #include <QHostAddress> CdcClient::CdcClient(QWidget *parent) : QDialog(parent) { client = new TcpClient(QHostAddress(QHostAddress::LocalHost), 3292); QVBoxLayout *layout = new QVBoxLayout; cmdTxt = new QLineEdit; sendButton = new QPushButton("Send"); sendButton->setEnabled(false); sendButton->setDefault(true); connectButton = new QPushButton("Connect"); connectButton->setEnabled(true); disconnectButton = new QPushButton("Disonnect"); disconnectButton->setEnabled(false); connect(sendButton, SIGNAL(clicked()), this, SLOT(sendCmd())); connect(connectButton, SIGNAL(clicked()), client, SLOT(connect())); connect(disconnectButton, SIGNAL(clicked()), client, SLOT(disconnect())); connect(client, SIGNAL(receivedData(const QString &)), this, SLOT(displayMsg(const QString &))); connect(client, SIGNAL(connected()), this, SLOT(set_connected())); connect(client, SIGNAL(disconnected()), this, SLOT(set_disconnected())); display = new QTextEdit(); status = new QLabel("Not connected"); layout->addWidget(cmdTxt); layout->addWidget(sendButton); layout->addWidget(display); layout->addWidget(connectButton); layout->addWidget(disconnectButton); layout->addWidget(status); setLayout(layout); setWindowTitle("CdC TCP Client"); } void CdcClient::set_connected() { status->setText("Connected"); sendButton->setEnabled(true); connectButton->setEnabled(false); disconnectButton->setEnabled(true); } void CdcClient::set_disconnected() { status->setText("Not connected"); sendButton->setEnabled(false); connectButton->setEnabled(true); disconnectButton->setEnabled(false); } void CdcClient::displayMsg(const QString &msg) { if ( msg[0] != '.' ) display->insertPlainText("CdC> " + msg); } void CdcClient::sendCmd() { QString cmd = cmdTxt->text(); client->sendData(cmd); client->sendData("redraw"); cmdTxt->setText(""); } void CdcClient::displayError(const QString &msg) { QMessageBox::critical(this, "CdcClient:", msg); } void CdcClient::quitting() { client->quitting(); } -------- I still have a small pb : if i quit the application, CdC also quits ; i guess it has to do with the socket not closing gracefully in this case but since i do not know how the TCP server handles it cannot fix it. Best wishes Jocelyn |
|
|
It should not close skychart when you quit your application. The normal way to close skychart is to send the "shutdown" command. To disconnect your client there is a "quit" command. Maybe send this command in quitting(). But if you just close your client and break the socket it must not do anything. For example if you telnet to skychart and exit telnet with ^] + quit, or kill the telnet process, this as no effect on the running skychart. I try to test with your client application but I am not fluent enough with Qt development. I success in compiling but the connect button as no effect at all. Can you attach to this issue a tar file including the main application and the qmake files. |
|
|
|
|
|
I've just uploaded a .tar.gz file containing the source files and a makefile (this is for MacOS 10.5.8 - you may have to regenerate the file with qmake for another platform). I works if i "manually" send the "quit" command using the GUI. But not if this command is sent automatically by the quitting() slot. There might be sth i dont understand about Qt signals here.. Btw, when talking to CdC from a telnet process, it's ok if i terminate the process by typing quit but _not_ if the telnet process is killed : CdC dies in this case (with a "broken pipe" msg..). |
|
|
Thank you for the file! I tested on my main Linux computer and all work fine, including exit from the program. With the Mac 10.5.8 I use to build the Mac packages I not have a Qt environment but killing telnet give me the same behavior you describe. I try to find a way to correct that or at least to handle correctly the exception. |
|
|
Revision 2179 fix the SIGPIPE crash. http://skychart.svn.sourceforge.net/viewvc/skychart?view=revision&revision=2179 Revision 2180 add the --verbose option to print a message when a command is received and when a chart is redraw. I look to add more information to this trace later. http://skychart.svn.sourceforge.net/viewvc/skychart?view=revision&revision=2180 The fix will be available with next Monday beta version. |
|
|
And revision 2181 add your example Qt client. Thank you! http://skychart.svn.sourceforge.net/viewvc/skychart?view=revision&revision=2181 |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 12-04-15 19:18 | JS | New Issue | |
| 12-04-16 11:04 | Patrick Chevalley | Note Added: 0002017 | |
| 12-04-16 11:04 | Patrick Chevalley | Status | new => feedback |
| 12-04-16 11:38 | JS | Note Added: 0002018 | |
| 12-04-16 11:38 | JS | Status | feedback => new |
| 12-04-17 16:16 | Patrick Chevalley | Note Added: 0002022 | |
| 12-04-18 22:18 | JS | Note Added: 0002025 | |
| 12-04-19 13:22 | Patrick Chevalley | Note Added: 0002026 | |
| 12-04-19 13:22 | Patrick Chevalley | Status | new => feedback |
| 12-04-19 17:29 | JS | File Added: cdc.tar.gz | |
| 12-04-19 17:35 | JS | Note Added: 0002027 | |
| 12-04-19 17:35 | JS | Status | feedback => new |
| 12-04-19 20:12 | Patrick Chevalley | Note Added: 0002028 | |
| 12-04-19 20:12 | Patrick Chevalley | Assigned To | => Patrick Chevalley |
| 12-04-19 20:12 | Patrick Chevalley | Status | new => assigned |
| 12-04-19 20:12 | Patrick Chevalley | Target Version | 0.3.0 => 3.8 |
| 12-04-20 13:32 | Patrick Chevalley | Note Added: 0002029 | |
| 12-04-20 13:32 | Patrick Chevalley | Status | assigned => resolved |
| 12-04-20 13:32 | Patrick Chevalley | Resolution | open => fixed |
| 12-04-20 13:32 | Patrick Chevalley | Fixed in Version | 0.3.0 => 3.7 SVN |
| 12-04-20 13:41 | Patrick Chevalley | Note Added: 0002030 | |
| 13-05-06 14:33 | Patrick Chevalley | Status | resolved => closed |