PDA

View Full Version : Creating a TcpServer listener class for MainWindow to use



TheVirus
16th April 2011, 06:06
I'm trying to get my MainWindow application launch a few TcpServer threads to wait for connections and go from there.

I am able to connect to the open port, but nothing gets triggered inside of Qt for me to go any further.

MainWindow.cpp:


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "serverlistener.h"
#include <QtNetwork/QTcpServer>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

if (!serverListener.listen(QHostAddress::LocalHost, 5600)) {
qCritical("Error opening port 5600.");
serverListener.close();
return;
}
}

MainWindow::~MainWindow()
{
delete ui;
}


MainWindow.h:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "serverlistener.h"

class ServerListener;
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;
ServerListener serverListener;

};

#endif // MAINWINDOW_H


ServerListener.cpp:


#include "serverlistener.h"
#include "mainwindow.h"
#include <iostream>
#include <QDebug>

using namespace std;

ServerListener::ServerListener(QObject *parent) :
QTcpServer(parent)
{
// serverSocket = new QTcpServer(this);

cout << "Listening" << endl;
}

ServerListener::~ServerListener() {
cout << "Destruction" << endl;
serverSocket->close();
}

void ServerListener::incomingConnection(int descriptor) {

cout << "Incoming connection" << endl;
//ServerThread *thread = new ServerThread(descriptor, this);

}



ServerListener.h:


#ifndef SERVERLISTENER_H
#define SERVERLISTENER_H

#include <QtNetwork/QTcpServer>
#include <QObject>

class ServerListener : public QTcpServer
{
Q_OBJECT;
public:
explicit ServerListener(QObject *parent = 0);
~ServerListener();

protected:
void incomingConnection(int descriptor);

private:
QTcpServer *serverSocket;
};

#endif // SERVERLISTENER_H


Here's my goal:



[listen1]<-------|MainWindow|------->[listen2]

[client1->listen1]
[client2->listen2]
[client3->listen1]
...
[client10->listen1]


Basically, I want to make sure the listening functions don't block the rest of the application. The program I'm making is quite advanced and this is my first time using Qt. I absolutely love the language and editor, which is why I chose it over VS2010 or VC#. I just hope I can accomplish what I have in mind (arrays/structs of sockets and structuring communication between them as needed).

Thanks.

wysota
16th April 2011, 09:18
You need to connect some signals to your socket. Have a look at networking examples that come with Qt.

TheVirus
16th April 2011, 17:49
You need to connect some signals to your socket. Have a look at networking examples that come with Qt.

I did look at it and I didn't see any connect() for the incomingConnection(), I thought that was inherited from the parent TcpServer class. I simply have a cout statement to see if that function is ever called and it is not, which is why I'm confused.

tbscope
16th April 2011, 20:07
I did look at it and I didn't see any connect() for the incomingConnection(), I thought that was inherited from the parent TcpServer class. I simply have a cout statement to see if that function is ever called and it is not, which is why I'm confused.

Without using the client socket, you'll not get far.
Take a look at this example: http://doc.qt.nokia.com/4.7/network-fortuneserver.html

Question:
Why do you inherit QTcpServer and create a QTcpServer in that same class?

Notes:
Your program will crash because you commented out important code. If you do that, always check that your code is valid.
The use of the word "thread" in your code without you understanding the basics of network programming and signals and slots doesn't bode well. You need to simplify your approach.

TheVirus
16th April 2011, 20:16
Without using the client socket, you'll not get far.
Take a look at this example: http://doc.qt.nokia.com/4.7/network-fortuneserver.html

Question:
Why do you inherit QTcpServer and create a QTcpServer in that same class?

Notes:
Your program will crash because you commented out important code. If you do that, always check that your code is valid.
The use of the word "thread" in your code without you understanding the basics of network programming and signals and slots doesn't bode well. You need to simplify your approach.

Right now, I'm using 'nc' to test my connection before going any further. I've looked at the fortune-server example several times and thought I was doing precisely what it was doing, just in a MainWindow instead of a QDialog.

The commented out 'new ServerListener' was from when I was not inheriting QTcpServer and was going about the server in a different way. I just left the commented code in there for future reference to myself that I've tried that method. I know the program will crash if I uncomment that code, that's why it's commented out :) I understand network programming just fine, just not the way Qt does it. I'm just not sure what I'm doing wrong and staring at the same examples for several hours isn't help either.

ChrisW67
17th April 2011, 00:51
Apart from the main window destructor derefrencing an uninitialised pointer the code as presented compiles and runs fine here.


chrisw@newton /tmp/simple_example $ ./simple_example
Listening
Incoming connection
Incoming connection
Incoming connection
Incoming connection
Destruction
Segmentation fault

I was using telnet to connect to port 5600 from two separate places.

Start by correcting the destructor, clean the build, run qmake, and rebuild.

TheVirus
18th April 2011, 00:01
Apart from the main window destructor derefrencing an uninitialised pointer the code as presented compiles and runs fine here.


chrisw@newton /tmp/simple_example $ ./simple_example
Listening
Incoming connection
Incoming connection
Incoming connection
Incoming connection
Destruction
Segmentation fault

I was using telnet to connect to port 5600 from two separate places.

Start by correcting the destructor, clean the build, run qmake, and rebuild.

I got it working somehow, but I'm redoing my approach so I can share a QList between classes (I need to keep track of connections). So, I'm going to make a new thread in a bit if I can't figure it out. In my other program (C), I used 'extern' to share the struct between files, let's hope Qt acts the same.

wysota
18th April 2011, 00:04
By saying "thread" do you mean "thread" or "class"? Because so far we have seen no threads in your code.

TheVirus
18th April 2011, 00:08
At the time, the goal was to detect incoming connections and then pass them off to a thread to be processed. Talking with someone on the IRC channel, he told me that using threads is pointless as they don't block like Java does. I do have the connections working and I can parse input, but I'm trying to add the connection's IP, port and text to a class so I can keep track of the connections and process them later.

ChrisW67
18th April 2011, 00:19
I got it working somehow,
Guessing and just pushing buttons until it "works somehow" is not a recipe for a reliable result.


In my other program (C), I used 'extern' to share the struct between files, let's hope Qt acts the same.
Qt is not a programming language. Why do you believe that using a library of routines, like Qt, is going to change the fundamental behaviour of the programming language (C/C++)?

wysota
18th April 2011, 00:49
Not that using a public global variable for sharing data is a good concept...

ChrisW67
18th April 2011, 01:27
Not that using a public global variable for sharing data is a good concept...
Indeed not, and even worse if you are talking about multiple threads accessing said global structure.

TheVirus
18th April 2011, 16:24
Guessing and just pushing buttons until it "works somehow" is not a recipe for a reliable result.


Qt is not a programming language. Why do you believe that using a library of routines, like Qt, is going to change the fundamental behaviour of the programming language (C/C++)?

I was reorganizing the .h files and removed some #includes and it worked after that. I think it was due to either a conflict or ordering of the includes.

I'm not hoping that Qt will change the way C++ works, I'm just unfamiliar with it. It's been years since I've done C++ programming and even when I was, I hardly used anything this advanced (never got into sockets, never got into data sharing). I don't claim to be a great programmer, in fact, I think I'm pretty basic, but I do have motivation and a willingness to learn. The way I learn is by doing. I can't read a book and then go work on some simple programs, because I'll get bored and not bother with it. I learn by giving myself a task and doing what it takes to complete it. Once it's completed, I then work on making it better and more efficient and try to use the more advanced features of the language than hacking something together as a band-aid.


Not that using a public global variable for sharing data is a good concept...

I'm just trying to follow what already works in a different method. I know I have a lot to learn of C++/Qt and I know that doing things just to get them to work is a poor excuse for bad coding practices and also leads to bad habits and a lack of learning, but it's what I'm used to and I'm trying to overcome it. Old habits die hard, and all that jazz. I thank you guys for your help and wouldn't have been able to get this far without this forum and IRC channel having me look at things in a different light.


Indeed not, and even worse if you are talking about multiple threads accessing said global structure.

Yeah, that's one challenge that I was putting off and was going to be "I'll cross that bridge when I get to it." but I realize that it would probably involve a rewrite of everything done up to that point. I know I need to do things right from the beginning and I know that the project I am undertaking is probably not one for a beginner, especially one with rusty C++ skills and no Qt knowledge. I've rarely used libraries in the past and did things in a really, really poor manner, but I always managed to get things done (college classes). I'm purely self-taught and if something worked then I'd never question it. I've never developed anything for use outside of my own personal needs or for anything major.

I realize my bad habits and poor style is causing more work for the people I'm asking for help and also realize that it will, potentially, lead to unanswered questions or the standard 'RTFM'. I may be new here but I can already tell this is a community that is about sharing knowledge and attention to detail. I plan on reading the documentation some more and start an outline of what I want to do and any roadblocks I'll run into. I'm not a coding perfectionist, as you can probably tell, but I do have an unquenchable thirst for knowledge. I must know why things work and how they work. I also hate it when people think poorly of me, even if it is over an anonymous forum.

I hope I can fix my issues and make the community proud.

<end of Mea Culpa>