一 一个服务器和一个客户端之间的通信
主窗口MyMainWindow.h
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <QWidget>
class MyMainWindow : public QWidget
{
Q_OBJECT
public:
explicit MyMainWindow(QWidget *parent = 0);
signals:
public slots:
};
#endif // MYMAINWINDOW_H
MyMainWindow.cpp
#include "MyMainWindow.h"
#include<QApplication>
#include"MyTcpClient.h"
#include<MyTcpServer.h>
MyMainWindow::MyMainWindow(QWidget *parent) : QWidget(parent)
{
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyTcpServer s; s.setWindowTitle("Sever"); s.show();
MyTcpClient c; c.setWindowTitle("Client"); c.show();
app.exec();
}
服务器端口MyTcpServer.h
#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H
#include <QWidget>
#include<QTcpServer> //需要在.pro文件中加QT += network
#include<QTcpSocket>
#include<QTextBrowser>
class MyTcpServer : public QWidget
{
Q_OBJECT
public:
explicit MyTcpServer(QWidget *parent = 0);
QTcpServer *_server;
QTcpSocket *_socket;
QTextBrowser *_show;
signals:
public slots:
void slotNewConnection();
void slotReadyRead();
};
#endif // MYTCPSERVER_H
服务器端口MyTcpServer.cpp
#include "MyTcpServer.h"
#include<QByteArray>
#include<QHBoxLayout>
#include<QNetworkInterface> //选择网址
MyTcpServer::MyTcpServer(QWidget *parent) : QWidget(parent)
{
//创建服务器用于监听
_server = new QTcpServer;
//第一个参数为网址,第二个参数为端口
_server->listen(QHostAddress::Any, 9988); //建立监听机制和端口,现在监听的是使用的IP地址
//通过一个槽函数建立起一个新的监听,当有一个新的连接时,触发槽的内容
connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
_show = new QTextBrowser;
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_show);
}
void MyTcpServer::slotNewConnection()
{
//获取多个TcpSocket,判断是否有未处理的连接,如果有就调用新的连接来处理连接的数据
while(_server->hasPendingConnections())
{
_show->append("new connection...");
//只要有新的连接就要建立一个TcpSocket
_socket = _server->nextPendingConnection();
connect(_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
}
}
void MyTcpServer::slotReadyRead()
{
//如果_socket中还有数据,就需要读出来
while(_socket->bytesAvailable() > 0)
{
_show->append("Data arrived... ");
//读出数据中所有的数据,通过readAll读取所有数据
QByteArray buf = _socket->readAll();
_show->append(buf);
}
}
客户端端口MyTcpClient.h
#ifndef MYTCPCLIENT_H
#define MYTCPCLIENT_H
#include <QWidget>
#include<QTcpSocket>
#include<QLineEdit>
class MyTcpClient : public QWidget
{
Q_OBJECT
public:
explicit MyTcpClient(QWidget *parent = 0);
QTcpSocket *_socket;
QLineEdit *_edit;
signals:
public slots:
void slotButtonClick();
};
#endif // MYTCPCLIENT_H
客户端端口MyTcpClient.cpp
#include "MyTcpClient.h"
#include<QHBoxLayout>
#include<QPushButton>
MyTcpClient::MyTcpClient(QWidget *parent) : QWidget(parent)
{
_socket = new QTcpSocket(this);
_socket->connectToHost("127.0.0.1", 9988);
_edit = new QLineEdit;
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_edit);
//通过截取return按键发送消息
connect(_edit, SIGNAL(returnPressed()), this, SLOT(slotButtonClick()));
QPushButton *button = new QPushButton("Submit");
layout->addWidget(button);
//通过点击Enter按键发送消息
connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClick()));
}
void MyTcpClient::slotButtonClick()
{
QString strText = _edit->text();
if(strText.isEmpty())
return;
else
_socket->write(strText.toUtf8()); //通过utf8格式转换为ByteArray格式
//将输入框制空
// _edit->setText("");
_edit->clear();
}
运行结果:
二 在上述程序的基础上增加IP地址选择窗口
头文件ChooseInterface.h,继承自QDialog
#ifndef CHOOSEINTERFACE_H
#define CHOOSEINTERFACE_H
#include <QDialog>
#include<QComboBox>
class ChooseInterface : public QDialog
{
Q_OBJECT
public:
explicit ChooseInterface(QWidget *parent = 0);
QComboBox *_combox;
QString _strSlelect; //将_combox中选择的内容保存到_strSelect中
signals:
public slots:
void slotsSelectAddress(QString str);
};
#endif // CHOOSEINTERFACE_H
源文件ChooseInterface.cpp
#include "ChooseInterface.h"
#include<QNetworkInterface>
#include<QVBoxLayout>
ChooseInterface::ChooseInterface(QWidget *parent) : QDialog(parent)
{
//get all interface,获取所有的IP地址
QList<QHostAddress> addrList = QNetworkInterface::allAddresses();
//返回所有的网口
// QList<QNetworkInterface> intefaceList = QNetworkInterface::allInterfaces();
//获取网口的入口地址
// QList<QNetworkAddressEntry> entryList = intefaceList.at(0).addressEntries();
//entryList又可以获取更详细的网络地址、网络地址等等
// QHostAddress add = entryList.at(0).broadcast();
_combox = new QComboBox(this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(_combox);
foreach(QHostAddress addr, addrList)
{
//先转为IPV4地址,再讲IPV4地址转化为字符串,如果是0就不用添加
quint32 tempAddr = addr.toIPv4Address();
if(tempAddr == 0)
continue;
else
_combox->addItem(QHostAddress(tempAddr).toString());
}
//选择框发生变化时,返回其内容
connect(_combox, SIGNAL(currentIndexChanged(QString)),this, SLOT(slotsSelectAddress(QString)));
}
void ChooseInterface::slotsSelectAddress(QString str)
{
this->_strSlelect = str;
}
#ifndef MYTCPCLIENT_H
#define MYTCPCLIENT_H
#include <QWidget>
#include<QTcpSocket>
#include<QLineEdit>
class MyTcpClient : public QWidget
{
Q_OBJECT
public:
explicit MyTcpClient(QWidget *parent = 0);
QTcpSocket *_socket;
QLineEdit *_edit;
signals:
public slots:
void slotButtonClick();
};
#endif // MYTCPCLIENT_H
源文件MyTcpClient.cpp
#include "MyTcpClient.h"
#include<QHBoxLayout>
#include<QPushButton>
MyTcpClient::MyTcpClient(QWidget *parent) : QWidget(parent)
{
_socket = new QTcpSocket(this);
_socket->connectToHost("127.0.0.1", 9988);
_edit = new QLineEdit;
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_edit);
//通过截取return按键发送消息
connect(_edit, SIGNAL(returnPressed()), this, SLOT(slotButtonClick()));
QPushButton *button = new QPushButton("Submit");
layout->addWidget(button);
//通过点击Enter按键发送消息
connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClick()));
}
void MyTcpClient::slotButtonClick()
{
QString strText = _edit->text();
if(strText.isEmpty())
return;
else
_socket->write(strText.toUtf8()); //通过utf8格式转换为ByteArray格式
//将输入框制空
// _edit->setText("");
_edit->clear();
}
头文件MyTcpServer.h
#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H
#include <QWidget>
#include<QTcpServer> //需要在.pro文件中加QT += network
#include<QTcpSocket>
#include<QTextBrowser>
class MyTcpServer : public QWidget
{
Q_OBJECT
public:
explicit MyTcpServer(QWidget *parent = 0);
QTcpServer *_server;
QTcpSocket *_socket;
QTextBrowser *_show;
signals:
public slots:
void slotNewConnection();
void slotReadyRead();
};
#endif // MYTCPSERVER_H
源文件:MyTcpServer.cpp
#include "MyTcpServer.h"
#include<QByteArray>
#include<QHBoxLayout>
#include<QNetworkInterface> //选择网址
#include"ChooseInterface.h"
#include<QMessageBox>
MyTcpServer::MyTcpServer(QWidget *parent) : QWidget(parent)
{
//创建服务器用于监听
_server = new QTcpServer;
//在监听之前就要选取IP地址
ChooseInterface* dlg = new ChooseInterface(this);
dlg->exec();
//提示选择的IP地址
QMessageBox::information(NULL,"You select the ip:", dlg->_strSlelect);
//为新选的地址分配服务
_server->listen(QHostAddress(dlg->_strSlelect), 9988);
//第一个参数为网址,第二个参数为端口
// _server->listen(QHostAddress::Any, 9988); //建立监听机制和端口,现在监听的是使用的IP地址
//通过一个槽函数建立起一个新的监听,当有一个新的连接时,触发槽的内容
connect(_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
_show = new QTextBrowser;
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_show);
}
void MyTcpServer::slotNewConnection()
{
//获取多个TcpSocket,判断是否有未处理的连接,如果有就调用新的连接来处理连接的数据
while(_server->hasPendingConnections())
{
_show->append("new connection...");
//只要有新的连接就要建立一个TcpSocket
_socket = _server->nextPendingConnection();
connect(_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
}
}
void MyTcpServer::slotReadyRead()
{
//如果_socket中还有数据,就需要读出来
while(_socket->bytesAvailable() > 0)
{
_show->append("Data arrived... ");
//读出数据中所有的数据,通过readAll读取所有数据
QByteArray buf = _socket->readAll();
_show->append(buf);
}
}
MyMainWindow.h
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <QWidget>
class MyMainWindow : public QWidget
{
Q_OBJECT
public:
explicit MyMainWindow(QWidget *parent = 0);
signals:
public slots:
};
#endif // MYMAINWINDOW_H
源文件MyMainWindow.cpp
#include "MyMainWindow.h"
#include<QApplication>
#include"MyTcpClient.h"
#include<MyTcpServer.h>
MyMainWindow::MyMainWindow(QWidget *parent) : QWidget(parent)
{
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyTcpServer s; s.setWindowTitle("Sever"); s.show();
MyTcpClient c; c.setWindowTitle("Client"); c.show();
app.exec();
}
运行结果:
3 UDP通信
头文件MyUdp1.h
#ifndef MYUDP1_H
#define MYUDP1_H
#include <QWidget>
#include<QUdpSocket>
#include<QTextBrowser>
class MyUdp1 : public QWidget
{
Q_OBJECT
public:
explicit MyUdp1(QWidget *parent = 0);
QUdpSocket *_udp;
QTextBrowser *_show;
signals:
public slots:
void slotReadyRead();
};
#endif // MYUDP1_H
源文件MyUdp1.cpp
#include "MyUdp1.h"
#include<QByteArray>
#include<QDebug>
#include<QTimer>
#include<QDateTime>
#include<QHostAddress>
#include<QVBoxLayout>
//udp效率高,每次发送的消息,交换机将udp消息排到头,udp丢了就丢了,tcp丢了就会重发
MyUdp1::MyUdp1(QWidget *parent) : QWidget(parent)
{
//内存被托管(加入父类中,如将该窗口加入到this中)之后
//每一个对象都有一个delete和deleteLater函数,delete立即释放,deleteLate等一会合适了再删除
_show = new QTextBrowser;
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(_show);
_udp = new QUdpSocket;
_udp->bind(10001);//绑定一个端口
connect(_udp, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
//每隔2秒给对方发送一个信息
QTimer *timer = new QTimer;
timer->setInterval(1000);
timer->start();
connect(timer, &QTimer::timeout, [this](){
quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
QString str = QString::number(timestamp);// 将整数转化为字符串
#if 0
_udp->writeDatagram(str.toUtf8(), QHostAddress("127.0.0.1"), 10002); //转为ByteArray发送
#endif
#if 0
_udp->writeDatagram(str.toUtf8(), QHostAddress::Broadcast, 10002);//通过10002端口进行广播
#endif
//多播广播
_udp->writeDatagram(str.toUtf8(), QHostAddress("224.1.1.131"), 10002);
});
}
void MyUdp1::slotReadyRead()
{
while(_udp->hasPendingDatagrams())
{
quint32 datagramSize = _udp->pendingDatagramSize();//获取报文大小
QByteArray buffer(datagramSize, 0);//申请空间大小
_udp->readDatagram(buffer.data(), buffer.size());//读取报文内容
// qDebug()<<buffer;//打印报文内容
_show->append(buffer);
}
}
头文件MyDup2.h
#ifndef MYUDP2_H
#define MYUDP2_H
#include <QWidget>
#include<QUdpSocket>
#include<QTextBrowser>
class MyUdp2 : public QWidget
{
Q_OBJECT
public:
explicit MyUdp2(QWidget *parent = 0);
QUdpSocket *_udp;
QTextBrowser *_show;
signals:
public slots:
void slotReadyRead();
};
#endif // MYUDP2_H
源文件MyDup2.cpp
#include "MyUdp2.h"
#include<QByteArray>
#include<QDebug>
#include<QTimer>
#include<QDateTime>
#include<QHostAddress>
#include<QVBoxLayout>
MyUdp2::MyUdp2(QWidget *parent) : QWidget(parent)
{
_show = new QTextBrowser;
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(_show);
_udp = new QUdpSocket;
_udp->bind(QHostAddress::AnyIPv4,10002);//绑定一个端口
_udp->joinMulticastGroup(QHostAddress("224.1.1.131"));//加入多播
connect(_udp, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
//每隔2秒给对方发送一个信息
QTimer *timer = new QTimer;
timer->setInterval(1000);
timer->start();
connect(timer, &QTimer::timeout, [this](){
quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
QString str = QString::number(timestamp);// 将整数转化为字符串
_udp->writeDatagram(str.toUtf8(), QHostAddress("127.0.0.1"), 10001); //转为ByteArray发送
});
}
void MyUdp2::slotReadyRead()
{
while(_udp->hasPendingDatagrams())
{
quint32 datagramSize = _udp->pendingDatagramSize();//获取报文大小
QByteArray buffer(datagramSize, 0);//申请空间大小
_udp->readDatagram(buffer.data(), buffer.size());//读取报文内容
// qDebug()<<buffer;//打印报文内容
_show->append(buffer);
}
}
运行结果: