1、新建一个QT项目,在.pro文件中导入网络模块包
QT += network
界面布局如下:
2、我们新建一个serversocket类,继承自QTcpSocket
serversocket.h
#ifndef SERVERSOCKET_H
#define SERVERSOCKET_H
#include <QTcpSocket>
#include <QHostAddress>
#include <QAbstractSocket>
class ServerSocket : public QTcpSocket
{
Q_OBJECT
public:
explicit ServerSocket(QObject *parent = 0,int serverSocketID=0);//在这里为它多加了serverSocketID,将TcpServer的SocketDescriptor传进来。
signals:
void serverSocketReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//自建的server类,通过这个信号,得到传输来的数据的来源及具体内容
void serverSocketDisConnect(qintptr serverSocketID,QString IP,int Port);//断开连接时,通过这个信号,Server类将容器idSocketMap内对应的套接字删除
private:
int serverSocketID;
private slots:
void ReadData();//具体实现读取数据
void DisConnect();
void outPutError(QAbstractSocket::SocketError);//qDebug输出套接字出错信息
};
#endif // SERVERSOCKET_H
serversocket.cpp
#include "serversocket.h"
ServerSocket::ServerSocket(QObject *parent,int serverSocketID) :
QTcpSocket(parent)
{
this->serverSocketID=serverSocketID;
connect(this,SIGNAL(readyRead()),this,SLOT(ReadData()));//挂接读取数据信号
connect(this,SIGNAL(disconnected()),this,SLOT(DisConnect()));//关闭连接时,发送断开连接信号
connect(this,SIGNAL(disconnected()),this,SLOT(deleteLater()));//关闭连接时,对象自动删除
connect(this,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(outPutError(QAbstractSocket::SocketError)));
}
void ServerSocket::ReadData()
{
//读取完整一条数据并发送信号
QByteArray data=this->readAll();
emit serverSocketReadData(this->serverSocketID,this->peerAddress().toString(),this->peerPort(),data);
}
void ServerSocket::DisConnect()
{
//断开连接时,发送断开信号
emit serverSocketDisConnect(this->serverSocketID,this->peerAddress().toString(),this->peerPort());
}
void ServerSocket::outPutError(QAbstractSocket::SocketError)
{
this->disconnectFromHost();
qDebug()<< this->errorString();
}
3、我们新建一个server类
server.h
#ifndef SERVER_H
#define SERVER_H
#include "serversocket.h"
#include <QTcpServer>
#include <QMap>
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
int serverSocketCount=0;//用于统计连接的用户数,
public:
QMap<int,ServerSocket *> idSocketMap;
QMap<int,QString> idUserMap;
protected:
void incomingConnection(qintptr serverSocketID);
signals:
void hasData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//这三个信号用于告诉dialog信息,用于dialog的UI的信息显示,比如更新显示用户连接数
void hasConnect(qintptr serverSocketID,QString IP,int Port);
void hasDisConnect(qintptr serverSocketID,QString IP,int Port);
void ListSocket(QMap<int,ServerSocket *> idSocketMap,QMap<int,QString> idUserMap);
private slots:
void ReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data);//连接到ServerSocket的void serverSocketReadData……信号
void DisConnect(qintptr serverSocketID,QString IP,int Port);
};
#endif // SERVER_H
server.cpp
#include "server.h"
#include "serversocket.h"
#include <QDebug>
#include <dialog.h>
Server::Server(QObject *parent) :
QTcpServer(parent)
{
}
//复写函数incomingConnection(qintptr serverSocketID)
void Server::incomingConnection(qintptr serverSocketID)
{
ServerSocket *serverSocket=new ServerSocket(this,serverSocketID);
serverSocket->setSocketDescriptor(serverSocketID);
connect(serverSocket,SIGNAL(serverSocketReadData(qintptr,QString,int,QByteArray)),
this,SLOT(ReadData(qintptr,QString,int,QByteArray)));
connect(serverSocket,SIGNAL(serverSocketDisConnect(qintptr,QString,int)),
this,SLOT(DisConnect(qintptr,QString,int)));
connect(serverSocket,SIGNAL(aboutToClose()),
this,SLOT(deleteLater()));//关闭监听时,对象自动删除
idSocketMap.insert(serverSocketID,serverSocket);
serverSocketCount++;
emit hasConnect(serverSocketID, serverSocket->peerAddress().toString(),serverSocket->peerPort());
emit ListSocket(idSocketMap,idUserMap);
}
void Server::ReadData(qintptr serverSocketID,QString IP,int Port,QByteArray data)
{
emit hasData(serverSocketID,IP,Port,data);
}
void Server::DisConnect(qintptr serverSocketID,QString IP,int Port)
{
idSocketMap.remove(serverSocketID);
idUserMap.remove(serverSocketID);
serverSocketCount--;
emit hasDisConnect(serverSocketID,IP,Port);
}
4、我们在主类中使用自定义的两个类
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "server.h"
#include <QTcpSocket>
#include <QMessageBox>
#include <QString>
#include <QStringList>
#include <string>
#include <QFile>
#include <QFileDevice>
#include <QIODevice>
#include <QTextStream>
#include <QMapIterator>
#include <string>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
QMap<int,ServerSocket *> ids;
QString read_ip_address();
private:
Ui::Dialog *ui;
Server *myserver;
QTcpSocket *tcpSocket;
QTcpSocket *tcpSocket1;
QTcpSocket *tcpSocket2;
signals:
void has_order(qintptr serverSocketID,QString IP,int Port,QString order);
void has_order_Broadcast(QString DATA);
public slots:
void updateCount();
void updateData(qintptr serverSocketID,QString IP,int Port,QByteArray data);
void judge_order(qintptr serverSocketID,QString IP,int Port,QString order);
void order_Broadcast(QString DATA);
private slots:
void on_pushButton_open_clicked();
void on_pushButton_close_clicked();
void on_pushButton_clear_clicked();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QHostAddress>
#include <QString>
#include <QNetworkInterface>
#include <qDebug>
int _count;
QByteArray data_all;
//=============构造函数===============================================================
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
_count=1;
myserver = new Server(this);
connect(myserver,SIGNAL(hasConnect(qintptr,QString,int)),this,SLOT(updateCount()));
connect(myserver,SIGNAL(hasDisConnect(qintptr,QString,int)),this,SLOT(updateCount()));
connect(myserver,SIGNAL(hasData(qintptr,QString,int,QByteArray)),
this,SLOT(updateData(qintptr,QString,int,QByteArray)));
connect(this,SIGNAL(has_order(qintptr,QString,int,QString)),
this,SLOT(judge_order(qintptr,QString,int,QString)));
connect(this,SIGNAL(has_order_Broadcast(QString)),
this,SLOT(order_Broadcast(QString)));
}
//=============虚造函数===============================================================
Dialog::~Dialog()
{
delete ui;
}
//=============查询本机IP==============================================================
QString Dialog::read_ip_address()
{
QString ip_address;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
ip_address = ipAddressesList.at(i).toString();
}
}
if (ip_address.isEmpty())
ip_address = QHostAddress(QHostAddress::LocalHost).toString();
return ip_address;
}
//=============开启服务器===============================================================
void Dialog::on_pushButton_open_clicked()
{
ui->pushButton_open->setEnabled(false);
ui->pushButton_close->setEnabled(true);
int Port = 6666;
//================================
ui->label_IP->setText(read_ip_address());
//================================
myserver->listen(QHostAddress::Any,Port);//监听客户端连接
ui->label_Port->setText(QString::number(Port));
ui->label_status->setText("运行中!");
}
//=============关闭服务器===============================================================
void Dialog::on_pushButton_close_clicked()
{
myserver->close();
ui->pushButton_close->setEnabled(false);
ui->pushButton_open->setEnabled(true);
ui->label_status->setText("关闭!");
ui->label_IP->setText("");
ui->label_Port->setText("");
ui->label_num->setText("0");
ui->plainTextEdit_show->clear();
}
//=============更新在线数===============================================================
void Dialog::updateCount()
{
ui->label_num->setText(QString::number(myserver->serverSocketCount));
QMap <int,ServerSocket *>::iterator OnLine;
}
//=============接收数据===============================================================
void Dialog::updateData(qintptr serverSocketID,QString IP,int Port,QByteArray data)
{
QString DATA=data;
QString str=QString("从 socket: %1 ip: %2 port: %3 收到\n->: %4").arg(serverSocketID).arg(IP).arg(Port).arg(DATA);
ui->plainTextEdit_show->appendPlainText(str);
if(DATA.startsWith('@')&&DATA.endsWith('#'))//judge if order
{
emit has_order(serverSocketID,IP,Port,DATA);
}
}
//========================================================·====================
void Dialog::judge_order(qintptr serverSocketID,QString IP,int Port,QString order)//judge which order
{
QByteArray change = order.toUtf8();
data_all=change;
QString ORDER=order.mid(1,order.length()-2);
QStringList List=ORDER.split(";");
if(List[0]==QString::fromLocal8Bit("data"))
{
emit has_order_Broadcast(order);
}
}
//=====================================================================
void Dialog::order_Broadcast(QString DATA)
{
QByteArray Broadcast = DATA.toUtf8();
QMap <int,ServerSocket *>::const_iterator Device;
for(Device=myserver->idSocketMap.constBegin();Device!=myserver->idSocketMap.constEnd();++Device)
{
Device.value()->write(Broadcast);
}
}
//=====================================================================
void Dialog::on_pushButton_clear_clicked()
{
ui->plainTextEdit_show->clear();
}