Qt Creator:Socket-Tcp-Udp

主要实现还是在代码中

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;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值