主要实现还是在代码中
Socket: 通常称为套接字。
Tcp:主要指的是传输层的TCP协议
Udp:用户数据报协议
主要是用TcpServer和TcpClient来接收数据和发送数据,主要是建立了三个窗口,server,client,widget(主窗口)。
需要注意的是IP地址的转换,用代码中的方法
还有就是使用Udp来接收和发送数据报,实现广播和多播的功能。
新建项目(我的项目名称为14IO)
14IO.pro
新建资源文件:
MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QFile>
#include <QPoint>
#include <QByteArray>//字节数组
#include <QDebug>
#include <QBuffer>
#include <QPixmap>
#include <QLabel>
#include <QTextStream>
#include <QDataStream>
#include "TcpServer.h"
#include "TcpClient.h"
#include "udp1.h"
#include "udp2.h"
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
signals:
public slots:
};
#endif // MYWIDGET_H
MyWidget.cpp
#include "MyWidget.h"
#include <QApplication>
/*
* 以下都是QIODevice的子类
* QFile 磁盘文件
* QBuffer // memory file 内存文件
* QTcpSocket
*
* 文件读写的另一种方法,“流”,io的方法
* QDataStream
* QTextStream
*/
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
#if 0
QFile file("../MyTest.txt");
file.open(QIODevice::ReadWrite);//打开的模式(读写)
file.write(QByteArray("abc"));
//file .seek()
//file.write()
file.close();
#endif
#if 0
QByteArray ba("薛国良");
QString str("薛国良");
qDebug() << ba.size() << str.size();//输出字节数9和3(字节数和字符数)
#endif
#if 0
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
buffer.write("hehe");
buffer.write("aabbbc");
buffer.close();
qDebug() << buffer.buffer();
#endif
#if 0
//发送一个图片
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);
QPixmap pixmap("E:/hehe.png");
pixmap.save(&buffer,"PNG");//将图片保存到buffer里面,格式为PNG(必须指明格式)
buffer.close();
qDebug() << buffer.buffer().size();//输出字节长度表明图片保存到内存中
//将图片接收并从内存中显示出来
QPixmap pixmap2;
pixmap2.loadFromData(buffer.buffer(),"PNG");//读取图片
QLabel *label = new QLabel(this);
label->setPixmap(pixmap2);
#endif
#if 0
//方便写入但是不方便再从文件中读取,方便读取使用DataStream
QFile file("E:/textstream.txt");
file.open(QIODevice::ReadWrite);
QTextStream textStream(&file);
textStream << 1 << "abc" << 1.2 << QString("abc");
file.close();
#endif
#if 0
//这样处理会出现乱码的情况
QFile file("E:/datastream.txt");
file.open(QIODevice::ReadWrite);
QDataStream dataStream(&file);
dataStream << 1 << "abc" << 1.2 << QString("abc") << QPoint(1,1);
file.close();
#endif
#if 0
QFile file("E:/datastream.txt");
file.open(QIODevice::ReadWrite);
QDataStream dataStream(&file);
int i;
char *buf;
double d;
QString str;
QPoint pt;
dataStream >> i >> buf >> d >> str >> pt;
qDebug() << i << buf << d << str << pt;
file.close();
#endif
#if 0
//虚拟内存
QFile file("E:/map.data");
file.open(QIODevice::ReadWrite);
file.seek(65535);//查找到64k内存的地方写入“1”
file.write("1");
file.close();
file.open(QIODevice::ReadWrite);
uchar *ptr = file.map(0,64*1024);//uchar(unsigned char)得到了一个映射内存(虚拟内存)
//写文件
*ptr = 'a';
ptr[1] = 'b';
//读文件
file.unmap(ptr);
file.close();
#endif
}
int main(int argc,char *argv[])
{
QApplication app(argc,argv);
#if 0
// MyWidget w;
// w.show();
TcpServer s;
s.show();
s.setWindowTitle("server");
TcpClient c;
c.show();
c.setWindowTitle("client");
#endif
Udp1 udp1;
udp1.show();
udp1.setWindowTitle("UDP1");
Udp2 udp2;
udp2.show();
udp2.setWindowTitle("UDP2") ;
return app.exec();
}
TcpClient.h//发送数据
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QWidget>
#include <QTcpSocket>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QPushButton>
class TcpClient : public QWidget
{
Q_OBJECT
public:
explicit TcpClient(QWidget *parent = 0);
QTcpSocket *_socket;
QLineEdit *_lineEdit;
signals:
public slots:
void slotButtonClick();
};
#endif // TCPCLIENT_H
TcpClient.cpp
#include "TcpClient.h"
TcpClient::TcpClient(QWidget *parent) :
QWidget(parent)
{
_socket = new QTcpSocket(this);
_socket->connectToHost("127.0.0.1",9988);
_lineEdit = new QLineEdit;
_lineEdit->setPlaceholderText("send message");
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_lineEdit);
QPushButton *button = new QPushButton("send");
layout->addWidget(button);
connect(button,SIGNAL(clicked()),this,SLOT(slotButtonClick()));
connect(_lineEdit,SIGNAL(returnPressed()),this,SLOT(slotButtonClick()));//敲击回车也能发送的信号
}
void TcpClient::slotButtonClick()
{
QString strText = _lineEdit->text();//接收文本信息
if(strText.isEmpty())
return;
_socket->write(strText.toUtf8());//发到服务器端
_lineEdit->clear();
}
TcpServer.h//接收数据并显示接收的数据
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QByteArray>
#include <QTextBrowser>//文本浏览器,继承于QTextEdit
#include <QHBoxLayout>
#include <QNetworkInterface>//用于选择网络
#include "ChooseInterFace.h"//需要在某个网口上监听,选择网口
#include <QMessageBox>
class TcpServer : public QWidget
{
Q_OBJECT
public:
explicit TcpServer(QWidget *parent = 0);
QTcpServer *_server;
QTcpSocket *_socket;
QTextBrowser *_show;
signals:
public slots:
void slotNewConnection();
void slotReadyRead();//接收数据的槽函数
};
#endif // TCPSERVER_H
TcpServer.cpp
#include "TcpServer.h"
TcpServer::TcpServer(QWidget *parent) :
QWidget(parent)
{
//创建服务器并且监听
_server = new QTcpServer;
ChooseInterFace dlg;
dlg.exec();//虽然窗口关闭了,但是dlg对象还存在着,函数结束后才会被析构
QMessageBox::information(NULL,"you choose ip:",dlg._strSelect);
_server->listen(QHostAddress(dlg._strSelect),9988);//监听端口
//当有客户端来连接时,调用slotNewConnection方法
connect(_server,SIGNAL(newConnection()),
this,SLOT(slotNewConnection()));
_show = new QTextBrowser;
//_show->setPlaceholderText("New message.....");
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(_show);
}
void TcpServer::slotNewConnection()
{
//判断是否有未处理的连接
while(_server->hasPendingConnections())//只要有连接,就获取,不然就只能获取一个
{
_socket = _server->nextPendingConnection();//获取一个QTcpSocket
//建立个信号槽,为新的socket什么时候有数据通知接收数据
connect(_socket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
}
}
void TcpServer::slotReadyRead()
{
//接收数据,判断是否有数据,如果有数据,通过readAll函数接收所有数据
while(_socket->bytesAvailable() > 0)//如果还有数据的话,就接收
{
_show->append("Data arrive....");
QByteArray buf = _socket->readAll();
_show->append(buf);//将buf里面的数据插入到QTextBrowser
}
}
下面主要实现Udp
注意的细节:广播和多播的函数是不一样的
udp1.h
#ifndef UDP1_H
#define UDP1_H
#include <QWidget>
#include <QUdpSocket>
#include <QHostAddress>
#include <QDebug>
#include <QByteArray>
#include <QTimer>
#include <QDateTime>
class Udp1 : public QWidget
{
Q_OBJECT
public:
explicit Udp1(QWidget *parent = 0);
QUdpSocket *_udp;
signals:
public slots:
void slotReadyRead();
};
#endif // UDP1_H
udp1.cpp
#include "udp1.h"
Udp1::Udp1(QWidget *parent) :
QWidget(parent)
{
_udp =new QUdpSocket;
_udp->bind(10001);//捆绑一个端口
connect(_udp,SIGNAL(readyRead()),
this,SLOT(slotReadyRead()));
//每隔一秒钟发送一个报文数据
QTimer *timer = new QTimer;
timer->setInterval(1000);
timer->start();
connect(timer,&QTimer::timeout,[&](){
quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
QString str = QString::number(timestamp);
#if 0
_udp->writeDatagram(str.toUtf8(),QHostAddress("127.0.0.1"),10002);//当前的毫秒数
#else
//_udp->writeDatagram(str.toUtf8(),QHostAddress::Broadcast,10002);//光播
_udp->writeDatagram(str.toUtf8(),QHostAddress("224.0.0.131"),10002);//多播
#endif
});
}
void Udp1::slotReadyRead()
{
while (_udp->hasPendingDatagrams())
{
quint32 datagramSize = _udp->pendingDatagramSize();//通过pendingDatagramSize()获取下个报文的数据大小
QByteArray buf(datagramSize,0);
_udp->readDatagram(buf.data(),buf.size());
qDebug() << "Udp1" << buf;
}
}
udp2.h
#ifndef UDP2_H
#define UDP2_H
#include <QWidget>
#include <QUdpSocket>
#include <QDateTime>
#include <QTimer>
#include <QByteArray>
class Udp2 : public QWidget
{
Q_OBJECT
public:
explicit Udp2(QWidget *parent = 0);
QUdpSocket *_udp;
signals:
public slots:
void slotReadyRead();
};
#endif // UDP2_H
udp2.cpp
#include "udp2.h"
Udp2::Udp2(QWidget *parent) :
QWidget(parent)
{
_udp =new QUdpSocket;
_udp->bind(QHostAddress::AnyIPv4,10002);//捆绑一个端口
_udp->joinMulticastGroup(QHostAddress("224.0.0.131"));//加入多播的Ip地址,接受数据
connect(_udp,SIGNAL(readyRead()),
this,SLOT(slotReadyRead()));
//每隔一秒钟发送一个报文数据
QTimer *timer = new QTimer;
timer->setInterval(1000);
timer->start();
connect(timer,&QTimer::timeout,[&](){
quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
QString str = QString::number(timestamp);
_udp->writeDatagram(str.toUtf8(),QHostAddress("127.0.0.1"),10001);//当前的毫秒数
});
}
void Udp2::slotReadyRead()
{
while (_udp->hasPendingDatagrams())
{
quint32 datagramSize = _udp->pendingDatagramSize();//通过pendingDatagramSize()获取下个报文的数据大小
QByteArray buf(datagramSize,0);
_udp->readDatagram(buf.data(),buf.size());
qDebug() << "Udp2" << buf;
}
}