//connection类
#ifndef CONNECTION_H
#define CONNECTION_H
#include
#include
#include
#include
#include
#include
class Connection:public QObject
{
Q_OBJECT
public:
int m_nSocketID;//-1 indicate the socket is invalid; else is the global id of the connection
int m_nMsgReceived;
int m_nMsgSent;
QTcpSocket* m_pTcpSocket;
public:
Connection(){m_nSocketID = -1;}
~Connection()
{
if (m_pTcpSocket!=NULL)
{
delete m_pTcpSocket;
}
}
public:
void InitializeConnection(QTcpSocket* socket, int id)
{
m_pTcpSocket = socket;
m_pTcpSocket->setParent(this);
m_nMsgReceived = 0;
m_nMsgSent = 0;
m_nSocketID = id;
}
void DeleteConnection()
{
m_nSocketID = -1;
m_pTcpSocket->disconnect();
// delete m_pTcpSocket; 若delete会报错, ?
m_pTcpSocket = NULL;
}
};
#endif
//server.h
#ifndef SERVER_H
#define SERVER_H
#include
#include
#include
#include
#include
#include
#include
#include "ui_base.h"
#include "qtheader.h"
#include "Connection.h"
class Server : public QMainWindow
{
Q_OBJECT
public:
Server(QWidget *parent = 0, Qt::WFlags flags = 0);
~Server();
private:
Ui::BaseClass ui;
public://public variables
QTcpServer* m_pTcpServer;
Connection* m_pConnection;
QMutex m_mutexConnection;//mutex to protect the array
int m_nConnected;
int m_nID;
public:
bool InitializeServers();
void ShowStatusMessage(const QString str);
public slots:
void OnNewConnection();
void OnReadyRead();
void OnDisconnected();
}
#endif
//server.cpp
/*! @function
********************************************************************************
Function : Server
Desc : constructor of the Server class, initialize the servers and variables
Params :
Return :
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
Server::Server(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
m_nSurveillanceID = 1;
m_nConnected = 0;
m_pConnection = new Connection[10];
if (!InitializeServers())
{
exit(-1);
}
}
/*! @function
********************************************************************************
Function : ~Server
Desc :
Params :
Return :
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
Server::~Server()
{
//ShowMessageBox("test");
delete m_pConnection;
}
/*! @function
********************************************************************************
Function : InitializeServers
Desc : initialize all the servers
Params :
Return :
if any initialization of the server failed, return false
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
bool Server::InitializeServers()
{
m_pTcpServer = new QTcpServer(this);
if (!m_pTcpServer->listen(QHostAddress("192.168.1.100"), 8745))
{
ShowMessageBox("server listen to 8745 error, exiting...");
return (false);
}
else
{
connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(OnNewConnection()));
}
return true;
}
/*! @function
********************************************************************************
Function : OnNewConnection
Desc : slot function, if there is new connection request, this function is called
Params :
Return :
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
void Server::OnNewConnection()
{
//check how many connections established
ShowStatusMessage("new connection...");
//find one connection to store the new connection
int i=0;
for (i=0; i<10; i++)
{
if (m_pConnection[i].m_nSocketID == -1)
{
break;
}
}
//add new connection
m_mutexConnection.lock();
(m_pConnection[i]).InitializeConnection(m_pTcpServer->nextPendingConnection(), m_nID);
connect(m_pConnection[i].m_pTcpSocket, SIGNAL(readyRead()), this, SLOT(OnReadyRead()));
connect(m_pConnection[i].m_pTcpSocket, SIGNAL(disconnected()), this, SLOT(OnDisconnected()));
m_mutexConnection.unlock();
//set the flags
m_nID++;
m_nConnected++;
//if the connection is 10, close the server
if (m_nConnected==10)
{
m_pTcpServer->close();
ShowStatusMessage("Maximum connection (10) reached, new connection will be refused......");
}
}
/*! @function
********************************************************************************
Function : OnReadyRead
Desc : slot function, if new data is available for server, this function is called
Params :
Return :
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
void Server::OnReadyRead()
{
}
/*! @function
********************************************************************************
Function : OnDisconnected
Desc : slot function, if the socket is disconnected from the server this function is called
Params :
Return :
Exception:
--------------------------------------------------------------------------------
Notes :
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
void Server::OnDisconnected()
{
//get the connection that disconnected from the server
QTcpSocket* socket = qobject_cast(sender());
Connection* connection = qobject_cast(socket->parent());
//delete the connection
m_mutexConnection.lock();
connection->DeleteConnection();
m_mutexConnection.unlock();
ShowStatusMessage("server disconnected");
m_nSurveillanceConnected--;
//if the connection is reduced from 10 to 9, reopen the server, listen
if (m_nSurveillanceConnected==9)
{
m_pTcpServerSurveillance->listen(QHostAddress("192.168.1.100"), 8745);
}
}
/*! @function
********************************************************************************
Function : ShowStatusMessage
Desc : show the message on the status bar
Params :
[IN] const QString str, the message to show
Return :
Exception:
--------------------------------------------------------------------------------
Notes : the status bar will be cleared first.
Examples :
--------------------------------------------------------------------------------
Author :
*******************************************************************************/
void Server::ShowStatusMessage(const QString str)
{
this->ui.statusBar->clearMessage();
this->ui.statusBar->showMessage(str);
}
几个问题简单说明:
1.这个不见得能够直接使用,是从我完整的程序中取出的一部分,根据需要再做调整;
2.这里为什么用的值指针保存connection,而不用list,vector等:
首先看看继承关系:QObject->QIODevice->QAbstractSocket->QTcpSocket,对于QObject这个类来说,是不能copy的,而从其派生的类也是同样不能复制的。如果使用list或vector,会调用到类似push_back这样的函数,其本质是复制,编译会报错的。这里就采用指针来解决这个问题。