关于QTcpServer服务器的学习
1.创建服务器
创建一个服务器对象;
栈上创建:QTcpServer server;
堆上创建:QTcpServer *server=new QTcpServer;
2.当服务器上有连接的时候,接收对方通信的套接字可以通过以下信号:
当有新的连接时,会自动执行
virtual void incomingConnection(qintptr handle);可以获得socket描述符,将socket描述符存在一个中间变量中。
此时,系统会产生一个newConnection()信号;
3.在设计当中,我们经常会用到自己定义的一些类型,如果也想用signal/slot传递的话,就需要注册类型
(1)首先要包含头文件
#include <QMetaType>
(2)在类型定义完成后,加入声明:Q_DECLARE_METATYPE(类型名称);例如下面代码:
class TextAndNumber {
public:
TextAndNumber();
TextAndNumber(int, QString);
int count();
QString text();
private:
int m_count;
QString m_text;
};
Q_DECLARE_METATYPE(TextAndNumber);
(3) 在main()函数中注册这种类型:
qRegisterMetaType<TextAndNumber>("TextAndNumber");
如果还希望使用这种类型的引用,可同样要注册:
qRegisterMetaType<TextAndNumber>("TextAndNumber&");
4.结合堆QTcpSocket和QTcpServer的理解,写了下面一段多线程的服务器
MySocket.h
#ifndef MYSOCKET_H
#define MYSOCKET_H
#include <QTcpSocket>
class MySocket:public QTcpSocket
{
Q_OBJECT
public:
MySocket();
public slots:
void writeData(QByteArray &value);
void readData();
signals:
void newData(QByteArray&message,quint16 port,QString &adress);
};
#endif // MYSOCKET_H
MySocket.cpp
#include "mysocket.h"
#include <QHostAddress>
#include <QDebug>
#include <QThread>
MySocket::MySocket()
{
connect(this,SIGNAL(readyRead()),this,SLOT(readData()),Qt::DirectConnection);
}
void MySocket::writeData(QByteArray &value)
{
this->write(value);
}
void MySocket::readData()
{
QByteArray message= this->readAll();
quint16 port=this->peerPort();
QString address=this->peerAddress().toString();
qDebug()<<"readData:"<<QThread::currentThreadId();
emit this->newData(message,port,address);
}
Myserver.h
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QTcpServer>
#include "mysocket.h"
class MyServer:public QTcpServer
{
Q_OBJECT
public:
MyServer();
bool startServer(QString ip,int port);
protected:
void incomingConnection(qintptr handle);
signals:
void serverStarted();
void newConnected(void* handle);
};
#endif // MYSERVER_H
MyServer.cpp
#include "myserver.h"
MyServer::MyServer()
{
}
bool MyServer::startServer(QString ip,int port)
{
bool res=false;
QHostAddress hostAddress=QHostAddress::Any;
if(ip!="All"){
hostAddress.setAddress(ip);
}
if(this->listen(hostAddress,port)){
res=true;
qDebug()<<("Server started ");
}
emit serverStarted();
return res;
}
void MyServer::incomingConnection(qintptr handle)
{
emit newConnected((void *)handle);
}
threadClient.h
#ifndef THREADCLIENT_H
#define THREADCLIENT_H
#include <QObject>
#include <QThread>
#include "mysocket.h"
class ThreadClient : public QThread
{
Q_OBJECT
public:
explicit ThreadClient(QObject *parent = 0);
void run();
public slots:
void newData(QByteArray& value,quint16 port ,QString& address);
void setNewConnection(void * handle);
signals:
void newDataSiganl(QByteArray &value, quint16 port, QString &address);
private:
MySocket*socket;
void *fd;
};
#endif // THREADCLIENT_H
threadClient.cpp
#include "threadclient.h"
ThreadClient::ThreadClient(QObject *parent) : QThread(parent)
{
fd=NULL;
}
void ThreadClient::run()
{
socket=new MySocket;
while(true){
if(fd!=NULL){
socket->setSocketDescriptor((qintptr)fd);
connect(socket,SIGNAL(newData(QByteArray&,quint16,QString&)),
this,SLOT(newData(QByteArray&,quint16,QString&)));
break;
}
}
this->exec();
}
void ThreadClient::newData(QByteArray &value, quint16 port, QString &address)
{
emit newDataSiganl(value,port,address);
}
void ThreadClient::setNewConnection(void *handle)
{
fd=(void *) (handle);
}
serverManager.h
#ifndef SERVERMANAGER_H
#define SERVERMANAGER_H
#include <QObject>
#include "myserver.h"
#include "mysocket.h"
#include <QThread>
#include <QHash>
#include "threadclient.h"
class ServerManager: public QObject
{
Q_OBJECT
public:
ServerManager();
public slots:
void newClient();
void newData(QByteArray& value,quint16 port ,QString& address);
void newConnection(void * handle);
signals:
void setNewConnetion(void *handle);
private:
MyServer*server;
QHash <int ,QString> clients;
int num;
ThreadClient *client;
void* Connection;
};
#endif // SERVERMANAGER_H
serverManager.cpp
#include "servermanager.h"
#include <QDebug>
#include <QThread>
ServerManager::ServerManager()
{
qDebug()<<"serverManager:"<<QThread::currentThreadId();
server=new MyServer;
connect(server,SIGNAL(newConnected(void *)),this,SLOT(newConnection(void *)),Qt::DirectConnection);
connect(server,SIGNAL(newConnection()),this,SLOT(newClient()));
server->startServer("All",6666);
num=0;
client=NULL;
}
void ServerManager::newData(QByteArray &message, quint16 port, QString &adress)
{
qDebug()<<"a new Data: "<<QThread::currentThreadId();
QString client1=QString::number(port)+":"+adress;
qDebug()<<message;
qDebug()<<port<<":"<<adress;
clients.insert(++num,client1);
}
void ServerManager::newConnection(void *handle)
{
Connection=handle;
}
void ServerManager::newClient()
{
client=new ThreadClient;
connect(this,SIGNAL(setNewConnetion(void *)),client,SLOT(setNewConnection(void*)));
connect(client,SIGNAL(newDataSiganl(QByteArray&,quint16,QString&)),this,
SLOT(newData(QByteArray&,quint16,QString&)));
client->start();
emit setNewConnetion(Connection);
}
main.cpp
#include <QCoreApplication>
#include "servermanager.h"
#include <QThread>
#include <QDebug>
#include <QByteArray>
#include <QMetaType>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<QByteArray>("QByteArray &");
qRegisterMetaType<QString>("QString &");
ServerManager manager;
qDebug()<<QThread::currentThreadId();
// QThread thread;
// manager.moveToThread(&thread);
// thread.start();
return a.exec();
}