客户端:
dialogclient.h
#ifndef DIALOGCLIENT_H
#define DIALOGCLIENT_H
#include <QDialog>
#include <QtNetwork>
namespace Ui {
class DialogClient;
}
//结构体
struct NetData
{
unsigned int length;
unsigned int n1;
double d1;
double d2;
char name[32]; //这里数组可以,注意如果是指针指向堆空间,堆里数据要自己copy
};
class DialogClient : public QDialog
{
Q_OBJECT
public:
explicit DialogClient(QWidget *parent = 0);
~DialogClient();
private slots:
void on_pushButtonConnect_clicked();
//连接成功
void OnSuccConnect();
//接收数据
void ReadStructDataAndShow();
private:
Ui::DialogClient *ui;
QTcpSocket *m_pTCPClient;
};
#endif // DIALOGCLIENT_H
dialogclient.cpp
#include "dialogclient.h"
#include "ui_dialogclient.h"
#include <QIntValidator>
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>
DialogClient::DialogClient(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogClient)
{
ui->setupUi(this);
//端口验证
QIntValidator *vali = new QIntValidator();
vali->setRange(0, 65535);
ui->lineEditPort->setValidator(vali);
//
ui->lineEditPort->setText("2000");
ui->lineEditIP->setText("127.0.0.1");
this->setLayout(ui->mainLayout);
//创建客户端
m_pTCPClient = new QTcpSocket();
//关联信号
connect(m_pTCPClient, SIGNAL(connected()), this, SLOT(OnSuccConnect()));
connect(m_pTCPClient, SIGNAL(readyRead()), this, SLOT(ReadStructDataAndShow()));
}
DialogClient::~DialogClient()
{
delete ui;
}
void DialogClient::on_pushButtonConnect_clicked()
{
int nPort = ui->lineEditPort->text().toInt();
QHostAddress address;
bool bres = address.setAddress(ui->lineEditIP->text());
//如果IP出错
if( ! bres )
{
QMessageBox::warning(this, tr("IP address error"), tr("IP address is not correct!"));
return;
}
//开始连接
m_pTCPClient->connectToHost(address, nPort);
}
void DialogClient::OnSuccConnect()
{
QMessageBox::information(this, tr("Connected"), tr("Connect successed."));
}
void DialogClient::ReadStructDataAndShow()
{
QString strMsg;
QByteArray dataArray = m_pTCPClient->readAll();
if(dataArray.length() != sizeof(NetData))
{
//长度不对
strMsg = tr("Receive error, struct length is %1 B, recv length is %2 B")
.arg(sizeof(NetData)).arg(dataArray.length());
qDebug()<<strMsg;
//
return;
}
//接收长度正确
const NetData* pData = (NetData*)(dataArray.data());
//显示
QString strShow = tr("NetData: \r\n");
strShow += tr("Length = %1\r\n").arg(pData->length);
strShow += tr("n1 = %1\r\n").arg(pData->n1);
strShow += tr("d1 = %1\r\n").arg(pData->d1);
strShow += tr("d2 = %1\r\n").arg(pData->d2);
strShow += tr("name = %1\r\n").arg(pData->name);
//显示
ui->labelShow->setText(strShow);
}
服务端:
dialogserver.h
#ifndef DIALOGSRV_H
#define DIALOGSRV_H
#include <QDialog>
#include <QtNetwork>
#include <QStringList>
#include <QList>
#include "clientjobs.h"
namespace Ui {
class DialogSrv;
}
//结构体
struct NetData
{
unsigned int length;
unsigned int n1;
double d1;
double d2;
char name[32]; //这里数组可以,注意如果是指针指向堆空间,堆里数据要自己copy
};
class DialogSrv : public QDialog
{
Q_OBJECT
public:
explicit DialogSrv(QWidget *parent = 0);
~DialogSrv();
private slots:
void on_pushButtonListen_clicked();
//两个信号的槽函数
void onNewConnection();
//
void DeleteOneClient(QString strIPAndPort);
void on_pushButtonStop_clicked();
void on_pushButtonSend_clicked();
private:
Ui::DialogSrv *ui;
//server
QTcpServer *m_pTCPSrv;
//保存客户列表
QStringList m_listIPAndPorts; //IP_Port
QList<ClientJobs*> m_listClients;//客户端
};
#endif // DIALOGSRV_H
dialogserver.cpp
#include "dialogsrv.h"
#include "ui_dialogsrv.h"
#include <QMessageBox>
#include <QIntValidator> //验证端口号
#include <QHostAddress>
#include <QByteArray>
#include <QDebug>
DialogSrv::DialogSrv(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogSrv)
{
ui->setupUi(this);
QIntValidator *vali = new QIntValidator();
vali->setRange(0, 65535);
ui->lineEditPort->setValidator(vali); //限制端口范围
ui->lineEditPort->setText("2000"); //默认监听端口
this->setLayout(ui->mainLayout); //设置界面排布
//构建TCP服务器
m_pTCPSrv = new QTcpServer(this);
//关联成功接收连接的信号
connect(m_pTCPSrv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}
DialogSrv::~DialogSrv()
{
delete m_pTCPSrv; m_pTCPSrv = NULL;
delete ui;
}
void DialogSrv::on_pushButtonListen_clicked()
{
if( m_pTCPSrv->isListening() )
{
//已经在监听,啥都不干
return;
}
//需要开启监听
//获取端口
int nPort = ui->lineEditPort->text().toInt();
bool bres = m_pTCPSrv->listen(QHostAddress::Any, nPort);
if(bres)
{
//成功
QMessageBox::information(this, tr("Listen"), tr("Listen successed."));
return;
}
else
{
//失败
QMessageBox::warning(this, tr("Listen"), tr("Listen failed."));
return;
}
}
void DialogSrv::onNewConnection()
{
//接收新连接
QTcpSocket *sockclient = m_pTCPSrv->nextPendingConnection();
//获取远端IP和端口
QString strIPAndPort = sockclient->peerAddress().toString() + tr(" __ %1").arg(sockclient->peerPort());
//添加到列表
ui->listWidget->addItem(strIPAndPort);
//构建客户端对象
ClientJobs *pClientJob = new ClientJobs(this, sockclient, strIPAndPort);
//IP-port列表
m_listIPAndPorts.append(strIPAndPort);
//客户端列表
m_listClients.append(pClientJob);
//
connect(pClientJob, SIGNAL(CallMainWindowDeleteClient(QString)), this, SLOT(DeleteOneClient(QString)));
}
void DialogSrv::on_pushButtonStop_clicked()
{
if(m_pTCPSrv->isListening())
{
m_pTCPSrv->close();
}
else
{
return;
}
}
//发送测试数据
void DialogSrv::on_pushButtonSend_clicked()
{
//判断有无客户端接入
if( m_listClients.count() < 1 )
{
return;
}
//判断选择的是哪个客户端
int nIndex = ui->listWidget->currentRow();
if(nIndex < 0)
{
//没选择客户端发送
return;
}
//使用向nIndex号客户端发包
//构造结构体
NetData ssData;
//填充数据
ssData.length = sizeof(NetData);
ssData.n1 = 1;
ssData.d1 = 2.0;
ssData.d2 = 4.0;
char name[32] = "Say Hello.";
strncpy(ssData.name, name, 32);
//转为QByteArray发送
QByteArray dataArray = QByteArray::fromRawData((char*)&ssData, sizeof(NetData));
m_listClients[nIndex]->SendBytes(dataArray);
//
qDebug()<<"Sendto: "<<m_listIPAndPorts[nIndex]<<" Bytes: "<<sizeof(NetData);
}
void DialogSrv::DeleteOneClient(QString strIPAndPort)
{
int nIndex = m_listIPAndPorts.indexOf(strIPAndPort);
if(nIndex < 0)
{
//序号出错
return;
}
//删除对应客户端
ui->listWidget->takeItem(nIndex); //删除UI显示的那一个IP条目
m_listIPAndPorts.removeAt(nIndex); //删除IP字符串列表对应条目
m_listClients.removeAt(nIndex);//删除客户端
}
clientjog.h
#ifndef CLIENTJOBS_H
#define CLIENTJOBS_H
#include <QObject>
#include <QtNetwork>
#include "clientjobs.h"
class ClientJobs : public QObject
{
Q_OBJECT
public:
explicit ClientJobs(QObject *parent, QTcpSocket *client, QString strIPPort);
//TCP连接
QTcpSocket *m_pClientSock;
QString m_strIPPort;//IP_Port
signals:
void CallMainWindowDeleteClient(QString m_strIPPort);
public slots:
void SendBytes(QByteArray &data);
void LostConnection();
};
#endif // CLIENTJOBS_H
clientjob.cpp
#include "clientjobs.h"
ClientJobs::ClientJobs(QObject *parent, QTcpSocket *client, QString strIPPort) :
QObject(parent)
{
m_pClientSock = client;
m_strIPPort = strIPPort;
//关联信号
connect(m_pClientSock, SIGNAL(disconnected()), this, SLOT(LostConnection()));
//可以关联接收数据信号readyRead(),这里不管
}
void ClientJobs::SendBytes(QByteArray &data)
{
m_pClientSock->write(data);
}
void ClientJobs::LostConnection()
{
//通知主窗口删除自己
emit CallMainWindowDeleteClient(m_strIPPort);
}