Results 1 to 8 of 8

Thread: Connected client tree

  1. #1
    Join Date
    Sep 2007
    Posts
    13
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Connected client tree

    I want to show the connected client in tree. I am able to create the tree but i having problem to remove it when a client is disconnected.

    Header file:
    Qt Code:
    1. #ifndef SERVER_H
    2. #define SERVER_H
    3.  
    4. #include <QDialog>
    5. #include <QList>
    6. #include <QHash>
    7.  
    8. class QLabel;
    9. class QTcpSocket;
    10. class QTextEdit;
    11. class QTcpServer;
    12. class QLineEdit;
    13. class QBuffer;
    14.  
    15. class Server : public QDialog
    16. {
    17. Q_OBJECT
    18.  
    19. public:
    20. Server(QWidget *parent = 0);
    21. ~Server();
    22.  
    23. protected:
    24. void sendToClients(const QByteArray& line);
    25.  
    26. private slots:
    27. //void sendMessage();
    28. void slotStartButtonEnable();
    29. void slotStartClicked();
    30. void slotStopClicked();
    31.  
    32. void slotNewClient();
    33. void slotClientDisconnected();
    34.  
    35. void slotSocketRead();
    36.  
    37. private:
    38. QList<QTcpSocket*> connections;
    39. QHash<QTcpSocket*, QBuffer*> buffers;
    40. //QHash<QTcpSocket*, int> itemList;
    41. QList<QTreeWidgetItem *> liClients;
    42. QTreeWidget *twClientConnected;
    43. QStringList slTreeLabel;
    44. QLineEdit *lePort;
    45. QLabel *lblPort;
    46. QLabel *lblStatus;
    47. QPushButton *btnQuit;
    48. QPushButton *btnStart;
    49. QPushButton *btnStop;
    50. QTcpSocket *serverSocket;
    51. QTcpServer *tcpServer;
    52. QTextEdit *teMessage;
    53. };
    54.  
    55. #endif
    To copy to clipboard, switch view to plain text mode 

    Source file:
    Qt Code:
    1. #include <QtGui>
    2. #include <QtNetwork>
    3. #include <QBuffer>
    4.  
    5. #include <stdlib.h>
    6.  
    7. #include "server.h"
    8.  
    9. Server::Server(QWidget *parent)
    10. : QDialog(parent)
    11. {
    12. lblPort = new QLabel(tr("Port:"));
    13. lePort = new QLineEdit;
    14. QRegExp regExp("[1-9][0-9]{0,4}");
    15. lePort->setValidator(new QRegExpValidator(regExp, this));
    16. lblPort->setBuddy(lePort);
    17.  
    18. btnStart = new QPushButton(tr("Start"));
    19. btnStop = new QPushButton(tr("Stop"));
    20. btnStart->setDisabled(true);
    21. btnStop->setDisabled(true);
    22.  
    23. QGroupBox *gbServerControl = new QGroupBox(tr("Server Control"));
    24. QGroupBox *gbMessage = new QGroupBox(tr("Message"));
    25. QGroupBox *gbConnectedClient = new QGroupBox(tr("Connected Client"));
    26.  
    27. twClientConnected = new QTreeWidget();
    28. twClientConnected->setColumnCount(2);
    29. slTreeLabel << tr("Address") << tr("Port");
    30. twClientConnected->setHeaderLabels(slTreeLabel);
    31. twClientConnected->header()->setStretchLastSection(false);
    32. twClientConnected->header()->setResizeMode(QHeaderView::Stretch);
    33. liClients.append(new QTreeWidgetItem(twClientConnected, QStringList(QString(""))));
    34. twClientConnected->addTopLevelItems(liClients);
    35. twClientConnected->takeTopLevelItem(0);
    36. twClientConnected->takeTopLevelItem(0);
    37.  
    38. lblStatus = new QLabel;
    39. lblStatus->setFrameShape(QLabel::Panel);
    40. lblStatus->setFrameShadow(QLabel::Sunken);
    41. lblStatus->setText(tr("Ready"));
    42.  
    43. btnQuit = new QPushButton(tr("Quit"));
    44. btnQuit->setAutoDefault(false);
    45.  
    46. teMessage = new QTextEdit(this);
    47. teMessage->setReadOnly(true);
    48.  
    49. tcpServer = new QTcpServer(this);
    50. serverSocket = new QTcpSocket(this);
    51.  
    52. connect(lePort, SIGNAL(textChanged(QString)), this, SLOT(slotStartButtonEnable()));
    53. connect(btnStart, SIGNAL(clicked()), this, SLOT(slotStartClicked()));
    54. connect(btnStop, SIGNAL(clicked()), this, SLOT(slotStopClicked()));
    55. connect(btnQuit, SIGNAL(clicked()), this, SLOT(close()));
    56. connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewClient()));
    57.  
    58. QHBoxLayout *portLayout = new QHBoxLayout;
    59. portLayout->addWidget(lblPort);
    60. portLayout->addWidget(lePort);
    61. portLayout->addStretch(1);
    62. portLayout->addWidget(btnStart);
    63. portLayout->addWidget(btnStop);
    64. gbServerControl->setLayout(portLayout);
    65.  
    66. QHBoxLayout *clientLayout = new QHBoxLayout;
    67. clientLayout->addWidget(twClientConnected);
    68. gbConnectedClient->setLayout(clientLayout);
    69.  
    70. QHBoxLayout *messageLayout = new QHBoxLayout;
    71. messageLayout->addWidget(teMessage);
    72. gbMessage->setLayout(messageLayout);
    73.  
    74. QHBoxLayout *bottomLayout = new QHBoxLayout;
    75. bottomLayout->addWidget(lblStatus, 1);
    76. bottomLayout->addWidget(btnQuit);
    77.  
    78. QVBoxLayout *mainLayout = new QVBoxLayout;
    79. mainLayout->addWidget(gbServerControl);
    80. mainLayout->addWidget(gbConnectedClient);
    81. mainLayout->addWidget(gbMessage);
    82. mainLayout->addLayout(bottomLayout);
    83. setLayout(mainLayout);
    84.  
    85. setWindowTitle(tr("TCP Chat Server - by Strife Low"));
    86. lePort->setFocus();
    87. }
    88.  
    89. Server::~Server()
    90. {
    91. }
    92.  
    93. void Server::sendToClients(const QByteArray& line)
    94. {
    95. foreach (QTcpSocket* connection, connections)
    96. {
    97. connection->write(line);
    98. }
    99. }
    100.  
    101. void Server::slotStartButtonEnable()
    102. {
    103. btnStart->setDisabled(false);
    104. }
    105.  
    106. void Server::slotStartClicked()
    107. {
    108. lblStatus->setText(tr("Server starting"));
    109. if (lePort->text() == "")
    110. {
    111. QMessageBox::critical(this, tr("Server"), tr("Please enter a valid port number"));
    112. return;
    113. }
    114. if (lePort->text().toInt() > 65535)
    115. {
    116. lePort->setText("65535");
    117. }
    118.  
    119. if (!tcpServer->listen(QHostAddress::Any, lePort->text().toInt())) {
    120. QMessageBox::critical(this, tr("Server"), tr("Unable to start the server: %1.").arg(tcpServer->errorString()));
    121. return;
    122. }
    123.  
    124. btnStart->setDisabled(true);
    125. btnStop->setDisabled(false);
    126. lePort->setDisabled(true);
    127. lblStatus->setText(tr("Server started at port %1").arg(tcpServer->serverPort()));
    128. }
    129.  
    130. void Server::slotStopClicked()
    131. {
    132. btnStart->setEnabled(true);
    133. btnStop->setEnabled(false);
    134. lePort->setDisabled(false);
    135.  
    136. if (tcpServer->isListening())
    137. {
    138. tcpServer->close();
    139. }
    140.  
    141. if (!connections.isEmpty())
    142. {
    143. foreach (QTcpSocket* connection, connections)
    144. {
    145. connection->close();
    146. }
    147. connections.clear();
    148. }
    149.  
    150. if (serverSocket->isValid())
    151. {
    152. serverSocket->close();
    153. }
    154. lblStatus->setText(tr("Server stopped"));
    155. }
    156.  
    157. void Server::slotNewClient()
    158. {
    159. if (!connections.isEmpty())
    160. {
    161. QByteArray msg = "New Client connected\n";
    162. foreach (QTcpSocket* connection, connections)
    163. {
    164. connection->write(msg);
    165. }
    166. }
    167.  
    168. serverSocket = tcpServer->nextPendingConnection();
    169. QStringList tmpClientAddressPort;
    170. tmpClientAddressPort << tr("%1").arg(serverSocket->peerAddress().toString()) << tr("%1").arg(serverSocket->peerPort());
    171. liClients.append(new QTreeWidgetItem(twClientConnected, tmpClientAddressPort));
    172.  
    173. //itemList.insert(serverSocket, (liClients.count() - 1));
    174. //tmpClientAddressPort.clear();
    175.  
    176. connections.append(serverSocket);
    177. QBuffer* buffer = new QBuffer(this);
    178. buffer->open(QIODevice::ReadWrite);
    179. buffers.insert(serverSocket, buffer);
    180. connect(serverSocket, SIGNAL(disconnected()), this, SLOT(slotClientDisconnected()));
    181. connect(serverSocket, SIGNAL(readyRead()), this, SLOT(slotSocketRead()));
    182. }
    183.  
    184. void Server::slotClientDisconnected()
    185. {
    186. QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
    187. QBuffer* buffer = buffers.take(socket);
    188. buffer->close();
    189. buffer->deleteLater();
    190. connections.removeAll(socket);
    191. socket->deleteLater();
    192.  
    193. QByteArray msg = "Client disconnected\n";
    194. foreach (QTcpSocket* connection, connections)
    195. {
    196. connection->write(msg);
    197. }
    198. }
    199.  
    200. void Server::slotSocketRead()
    201. {
    202. QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
    203. QBuffer* buffer = buffers.value(socket);
    204.  
    205. qint64 bytes = buffer->write(socket->readAll());
    206. buffer->seek(buffer->pos() - bytes);
    207.  
    208. while (buffer->canReadLine())
    209. {
    210. QByteArray line = buffer->readLine();
    211. sendToClients(line);
    212. teMessage->append(line);
    213. }
    214. }
    215.  
    216. // end of file
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Connected client tree

    Hmm... why is serverSocket a member variable of the class?

    Anyway... I don't see any code for removing an item from the tree, so I'm not surprised that entries are not removed

  3. #3
    Join Date
    Sep 2007
    Posts
    13
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Connected client tree

    Quote Originally Posted by wysota View Post
    Anyway... I don't see any code for removing an item from the tree, so I'm not surprised that entries are not removed
    Thats what Im asking for. How am I suppose to remove the list.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Connected client tree

    QTreeWidget::takeTopLevelItem() and QList::removeAt() are certainly things to start with.

  5. #5
    Join Date
    Sep 2007
    Posts
    13
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Connected client tree

    =.=
    I know which function to use to remove the list. But its not as easy as just using that function. Anyway, I will just keep trying myself 1st. Thanks for the reply.
    Last edited by cooler123; 28th September 2007 at 05:05.

  6. #6
    Join Date
    Sep 2007
    Posts
    13
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Connected client tree

    Still having problem in removing the list. Can anyone please help?
    Qt Code:
    1. void Server::slotNewClient()
    2. {
    3. if (!connections.isEmpty())
    4. {
    5. QByteArray msg = "New Client connected\n";
    6. foreach (QTcpSocket* connection, connections)
    7. {
    8. connection->write(msg);
    9. }
    10. }
    11.  
    12. serverSocket = tcpServer->nextPendingConnection();
    13. QStringList tmpClientAddressPort;
    14. tmpClientAddressPort << tr("%1").arg(serverSocket->peerAddress().toString()) << tr("%1").arg(serverSocket->peerPort());
    15.  
    16. itemList.insert(serverSocket, liClients.count());
    17. liClients.append(new QTreeWidgetItem(twClientConnected, tmpClientAddressPort));
    18.  
    19. connections.append(serverSocket);
    20. QBuffer* buffer = new QBuffer(this);
    21. buffer->open(QIODevice::ReadWrite);
    22. buffers.insert(serverSocket, buffer);
    23. connect(serverSocket, SIGNAL(disconnected()), this, SLOT(slotClientDisconnected()));
    24. connect(serverSocket, SIGNAL(readyRead()), this, SLOT(slotSocketRead()));
    25. }
    26.  
    27. void Server::slotClientDisconnected()
    28. {
    29. QMessageBox::critical(this, tr("Server"), tr("list count: %1.").arg(liClients.count()));
    30. QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
    31. for (int j = 0; j < (twClientConnected->topLevelItemCount()); j++)
    32. {
    33. if (liClients.at(itemList.take(socket)) == twClientConnected->topLevelItem(j))
    34. {
    35. twClientConnected->takeTopLevelItem(0);
    36. liClients.removeAt(itemList.take(socket));
    37. }
    38. }
    39. QBuffer* buffer = buffers.take(socket);
    40. buffer->close();
    41. buffer->deleteLater();
    42. connections.removeAll(socket);
    43. socket->deleteLater();
    44.  
    45. QByteArray msg = "Client disconnected\n";
    46. foreach (QTcpSocket* connection, connections)
    47. {
    48. connection->write(msg);
    49. }
    50. }
    To copy to clipboard, switch view to plain text mode 

    itemList is:
    QHash<QTcpSocket*, int> itemList;

  7. #7
    Join Date
    Sep 2007
    Location
    Szczecin, Poland
    Posts
    153
    Thanks
    7
    Thanked 11 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Connected client tree

    I suggest you to use sender() method to find a singnal emitting object if signal connected to this slot is emited by socket object, and add additional QMap<QTcpSocket*, QTreeWidgetItem*>

    It will be easy to find what exactly you should remove i think...

  8. #8
    Join Date
    Jan 2009
    Posts
    7
    Thanks
    2

    Default Re: Connected client tree

    Quote Originally Posted by wysota View Post
    Hmm... why is serverSocket a member variable of the class?

    Anyway... I don't see any code for removing an item from the tree, so I'm not surprised that entries are not removed
    Firstly let start by saying that I am sorry for bumping such an old thread.

    I'm interested in creating a simple chat application. There's a server to which the various clients connect.

    My first doubt comes from the above quote: I don't understand the question. Is there any problem in having serverSocket as a member variable of the class server??
    (I'm a very recent member of this board, but from what I could read I know that wysota as a great understanding not only of the Qt framework but also of the C++ language. So clearly there's some "problem" in there )


    But that is not my only doubt. I was hoping someone could shed some light on the functioning of this kind of application.
    What strategy do you recomend for someone who's new to the framework?

    I intend to use tcpsockets and threads.
    In my understanding, and after reading the various examples that came with the Qt documentation, I think that the application should perform as follows:

    on one side there's the server. It has got a serversocket responsible for handling the connections of the new clients. And for each connection (client) i should start a new thread responsible for analising the type of communication: login, logout, message, etc. and send the corresponding answer to the client(s).

    In the threadedfortuneserver example, each thread does the same thing: creates a new socket with the socket_descriptor passed by the server, sends the fortune and disconnects the socket.

    I think that, in a chat application the sockets should remain open as long as the client is connected to server, correct?

    Also, each socket should be able to access the list of the connected clients at a given time.
    What data structure do you recommend that I should use that information (and also, what is the information that I should store), an HashMap<username, socket *>??

    When a client sends data, that data is read and analised by the corresponding thread and, in case it's a message it's sent to all the other clients:

    foreach(tcpsocket *, socket_list)
    tcpsocket.write(msg)

    is this correct??
    Is there any other way (a better way) for doing this??

    I really sorry for such a long post and I hope someone can help me.

    Thank you all.

Similar Threads

  1. QTcpSocket Chat : Mutiple Client using FD_SET and select()
    By cooler123 in forum Qt Programming
    Replies: 20
    Last Post: 15th January 2012, 19:57
  2. Optimizing filterAcceptsRow() to filter a tree
    By vfernandez in forum Qt Programming
    Replies: 1
    Last Post: 4th January 2007, 12:50
  3. synching client readings to server output
    By OnionRingOfDoom in forum Qt Programming
    Replies: 14
    Last Post: 28th January 2006, 18:15

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.