Results 1 to 5 of 5

Thread: Multiple TcpClients to multiple Servers

  1. #1
    Join Date
    Jun 2012
    Posts
    13
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Multiple TcpClients to multiple Servers

    It's not done obviously but I'm trying to put together the basics for a test executive that creates multiple client connections where each client connects to a different server. So I've created a ConnectionMgr class that is supposed to handle each of the connections using a map that ties the serverName to a TcpClient class. In the TcpClient class I create the connections and the signals for receiving data.

    My current problem is that I'm getting compile errors in the TcpClient class that says I have multiple definitions of ReadTcpData, Connected, Disconnected, etc. It appears that its having problems with the fact that I'm creating multiple instances of the TcpClient class.

    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.o:-1: In function `TcpClient::ReadTcpData()':
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.cpp:104: multiple definition of `TcpClient::ReadTcpData()'
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/../B2TestSet/tcpclient.cpp:37: error: first defined here
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.o:-1: In function `TcpClient::Connected()':
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.cpp:110: multiple definition of `TcpClient::Connected()'
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/../B2TestSet/tcpclient.cpp:47: error: first defined here
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.o:-1: In function `TcpClient:isconnected()':
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.cpp:116: multiple definition of `TcpClient:isconnected()'
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/../B2TestSet/tcpclient.cpp:52: error: first defined here
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.o:-1: In function `TcpClient::ErrHandler(QAbstractSocket::SocketErro r)':
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/moc_tcpclient.cpp:122: multiple definition of `TcpClient::ErrHandler(QAbstractSocket::SocketErro r)'
    .../QtProjects/B2TestSet-build-desktop-Desktop_Qt_4_8_1_for_GCC__Qt_SDK__Debug/../B2TestSet/tcpclient.cpp:57: error: first defined here

    I'm not sure if this is the best way to manage multiple client connections. If somebody has a better idea for a simpliar approach I would be interested.

    Qt Code:
    1. mainwindow.cpp
    2. ***************************************
    3.  
    4. MainWindow::MainWindow(QWidget *parent) :
    5. QMainWindow(parent),
    6. ui(new Ui::MainWindow)
    7. {
    8. ui->setupUi(this);
    9.  
    10. ....
    11.  
    12. // Instantiate a connection manager
    13. ConnectionMgr *conMgr = new ConnectionMgr(_serverMap, this);
    14. conMgr->ConnectAll();
    15. }
    16.  
    17. connectionmgr.cpp
    18. ***************************************
    19. #include "connectionMgr.h"
    20.  
    21. ConnectionMgr::ConnectionMgr(std::map<string, string>serverMap, QObject *parent) :
    22. QObject(parent)
    23. {
    24. _serverMap = serverMap;
    25. }
    26.  
    27. void ConnectionMgr::ConnectAll()
    28. {
    29. map<string, string>::iterator it;
    30.  
    31. // Attempt to connect to the list of servers
    32. // and add each client to a client map
    33. for(it = _serverMap.begin(); it != _serverMap.end(); it++)
    34. {
    35. QString srvName = QString::fromStdString((*it).first);
    36. QString srvInfo = QString::fromStdString((*it).second);
    37. NetInfo netInfo = ParseSrvInfo( srvInfo );
    38.  
    39. TcpClient *tcpClient = new TcpClient(netInfo.ipAddr, netInfo.port, this);
    40. _clientMap[srvName.toStdString()] = tcpClient;
    41. }
    42. }
    43.  
    44. connectionmgr.h
    45. ***************************************
    46. #ifndef CONNECTIONMGR_H
    47. #define CONNECTIONMGR_H
    48.  
    49. #include "qstring.h"
    50. #include "qtcpsocket.h"
    51. #include "qstringlist.h"
    52. #include "tcpclient.h"
    53.  
    54. using namespace std;
    55.  
    56. struct NetInfo
    57. {
    58. QString ipAddr;
    59. int port;
    60. };
    61.  
    62. class ConnectionMgr : public QObject
    63. {
    64. Q_OBJECT
    65.  
    66. public:
    67. ConnectionMgr(map<string, string>serverMap, QObject *parent = 0);
    68. ~ConnectionMgr();
    69.  
    70. TcpClient *GetTcpClient(QString srv);
    71. void ConnectAll();
    72.  
    73. private:
    74. map<string, string>_serverMap;
    75. map<string, TcpClient*>_clientMap;
    76.  
    77. NetInfo GetSrvInfo( QString srvName );
    78. NetInfo ParseSrvInfo( QString srvInfo );
    79. };
    80.  
    81. #endif // CONNECTIONMGR_H
    82.  
    83. tcpclient.cpp
    84. ***************************************
    85. #include "tcpclient.h"
    86.  
    87. TcpClient::TcpClient(QObject *parent) :
    88. QObject(parent)
    89. {
    90. _isConnected = false;
    91. }
    92.  
    93. TcpClient::TcpClient(QString ipAddr, int port, QObject *parent) :
    94. QObject(parent)
    95. {
    96. _isConnected = false;
    97. Connect(ipAddr, port);
    98. }
    99.  
    100. void TcpClient::Connect(QString ipAddr, int port)
    101. {
    102. // When it did compile a segment fault occurs when the connect is called
    103. _tcpClient = new QTcpSocket();
    104. connect(_tcpClient, SIGNAL(readyRead()),SLOT(ReadTcpData()));
    105. connect(_tcpClient, SIGNAL(connected()),SLOT(Connected()));
    106. connect(_tcpClient, SIGNAL(disconnected()),SLOT(Disconnected()));
    107. connect(_tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),
    108. SLOT(ErrHandler(QAbstractSocket::SocketError)));
    109. _tcpClient->connectToHost(ipAddr, port);
    110. }
    111.  
    112. qint64 TcpClient::Write(const char* data)
    113. {
    114. qint64 bytesWritten = 0;
    115. if(_tcpClient->waitForConnected(5000))
    116. bytesWritten = _tcpClient->write(data);
    117.  
    118. return bytesWritten;
    119. }
    120.  
    121. void TcpClient::ReadTcpData()
    122. {
    123. QByteArray data = _tcpClient->readAll();
    124. // Need to probably add an emit of some sort here
    125. }
    126.  
    127. bool TcpClient::IsConnected()
    128. {
    129. return _isConnected;
    130. }
    131.  
    132. void TcpClient::Connected()
    133. {
    134. _isConnected = true;
    135. }
    136.  
    137. void TcpClient::Disconnected()
    138. {
    139. _isConnected = false;
    140. }
    141.  
    142. void TcpClient::ErrHandler(QAbstractSocket::SocketError socketError)
    143. {
    144. QString errStr;
    145. switch (socketError)
    146. {
    147. case QAbstractSocket::RemoteHostClosedError:
    148. errStr = "TcpClient error: The remote host closed the connection.";
    149. break;
    150. case QAbstractSocket::HostNotFoundError:
    151. errStr = "TcpClient error: The host was not found.";
    152. break;
    153. case QAbstractSocket::ConnectionRefusedError:
    154. errStr = "TcpClient error: The connection was refused by the peer.";
    155. break;
    156. default:
    157. errStr = tr("TcpClient error: %1").arg(_tcpClient->errorString());
    158. break;
    159. }
    160. }
    161.  
    162. void TcpClient::Disconnect()
    163. {
    164. _tcpClient->disconnect();
    165. }
    166.  
    167. tcpclient.h
    168. ***************************************
    169. #ifndef TCPCLIENT_H
    170. #define TCPCLIENT_H
    171.  
    172. #include <QObject>
    173. #include "qtcpsocket.h"
    174.  
    175. using namespace std;
    176.  
    177. class TcpClient : public QObject
    178. {
    179. Q_OBJECT
    180. public:
    181. explicit TcpClient(QObject *parent = 0);
    182. explicit TcpClient(QString ipAddr, int port, QObject *parent = 0);
    183. ~TcpClient();
    184.  
    185. void Connect(QString ipAddr, int port);
    186. bool IsConnected();
    187. qint64 Write(const char* data);
    188. void Disconnect();
    189.  
    190. signals:
    191. void ReadTcpData();
    192. void Connected();
    193. void Disconnected();
    194. void ErrHandler(QAbstractSocket::SocketError socketError);
    195.  
    196. public slots:
    197.  
    198. private:
    199. QTcpSocket* _tcpClient;
    200. bool _isConnected;
    201. };
    202.  
    203. #endif // TCPCLIENT_H
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Multiple TcpClients to multiple Servers

    TcpClient::ReadTcpData(), Connected(), Disconnected() and ErrHandler() are declared as signals not slots: you do not provide implementations for signals because they are generated by moc. I think you intend these to be slots based on earlier attempts to connect to them as slots.

  3. #3
    Join Date
    Jun 2012
    Posts
    13
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Multiple TcpClients to multiple Servers

    You're absolutely right. Thanks so much for taking the time to look at it.

    I have another question if you don't mind. In the TcpClient class readyRead() signal is there a way of sending the client socket connection that received/generated the readyRead() to the slot that receives the signal? In other words I would like to have a common slot routine which not only reads the receiving message but knows which server connection it received the data on for communicating back to that server. As I have it now each TcpClient connection has its own slot routine and from this I was planning on emitting/relaying the client connection and data to the subscriber. Is what I'm doing the best way of accomplishing what I want?

    Also if I continue with my current approach, I would like to connect, I guess effectively signals from each TcpClient object to a slot in MainWindow. Does this have to be relayed or re-emitted through ConnectionMgr or is there a more efficient way to connect directly to emits from the TcpClient to slots in the MainWindow.

    Thanks again for your time.
    Last edited by sa5webber; 20th June 2012 at 19:03.

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Multiple TcpClients to multiple Servers

    There is no TcpClient::readyRead() signal declared that I can see. Assuming you mean readyRead() emitted by TcpClient::_tcpClient then you can connect it to a slot in TcpClient that simply emits a signal, defined on TcpClient, that carries the TcpClient address to any listeners. Passing the QTcpSocket's address would allow external access to the private member variable: possibly not a good idea..

  5. #5
    Join Date
    Jun 2012
    Posts
    13
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Multiple TcpClients to multiple Servers

    Yes the readyRead() signal is not defined in TcpClient.h segment here. When I entered this listing I was still trying to resolve the errors I had asked about with this listing which as you pointed out was due to me still getting my head around the signal/slot naming convention. That mistake has definitely made that clearer to me.

    In any event I have what I was asking about working with the ConnectionMgr receiving and re-emitting each of the TcpClient signals to the MainWindow. So in this case I might have actually answered my own question. Again I can't tell you how much I appreciate and admire all of the help people like you provide to this forum. I'm sure I'll have other questions as I forage my way through QT. Thanks for being there.

Similar Threads

  1. using one signal to update multiple multiple controls
    By henryjoye in forum Qt Programming
    Replies: 7
    Last Post: 13th December 2011, 14:19
  2. Replies: 2
    Last Post: 19th October 2011, 09:30
  3. Replies: 1
    Last Post: 17th May 2011, 16:12
  4. Multiple use of QGraphicScene
    By Xtresis in forum Newbie
    Replies: 4
    Last Post: 6th September 2010, 12:06
  5. Replies: 0
    Last Post: 21st December 2006, 11:48

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.