QT5 网络通讯

QT5 TCP网络通讯

  • 服务器与客户端建立连接listen() - connectToHost();  触发newPendingConnect信号
  • 实时数据通讯write(); read();  触发readyRead信号

通讯主要使用的类:

QTcpServer  Class

QTcpServer类提供了一个基于TCP的服务器。
这个类可以接受传入的TCP连接。您可以指定端口或让QTcpServer自动选择一个端口。您可以收听特定地址或所有机器的地址。
调用listen()让服务器侦听传入的连接。每次客户端连接到服务器时,都会发出newConnection()信号。

QTcpSocket Class

QTcpSocket类提供了一个TCP套接字。
TCP(传输控制协议)是一种可靠的,面向流的,面向连接的传输协议。 它特别适合连续传输数据。
QTcpSocket是QAbstractSocket的一个方便的子类,它允许你建立一个TCP连接并传输数据流。

建立连接:

服务器端以监听的方式监听客服端是否有连接请求

客户端以调用connectToHost()函数主动连接服务器端

tcp协议服务器端实现流程

建立服务器对象

listen服务器, 通过建立的服务器 监听指定地址/端口的客服端;判断是否有客户连接有连接就触发newConnection();

通过connect处理newConnection()信号;

    server = new QTcpServer(this); //建立一个服务器对象
    server->listen(QHostAddress::Any, 8000);//通过建立的服务器监听指定ip地址及端口号的客服端,如不指定端口号,系统会随机分配
    connect(server, QTcpServer::newConnection,
    [=]()
    {
        qDebug() << "有连接进来";
    }
    );

tcp协议客户端实现流程

建立QTcpSocket套节字(ip,端口)

通过套节字connectToHost()函数主动连接服务器;连接成功则触发服务器QTcpServer::newConnection信号;并发送套节字到服务器端;

关闭连接;

QTcpSocket Sc(this);
Sc.connectToHost("127.0.0.1", 8888);//实际代码中参数要进行类型转化
Sc.close();

实时通讯:

  • 客户端到服务器端通讯
  1. 当客户端与服务器端建立连接后;
  2. 客户端与服务器端通讯在客户端通过套节字对象调用write()函数发送上传内容;
  3. 服务器端有客户端数据写入时服务器端会自动调用readyread信号
  4. 服务器端在connect中处理readyread信号,并由nextPendingConnection()函数接收客户端发送的套节字;
  5. 服务器端对接收的套节字进行相应处理,即完成一次客户端到服务器端的通讯
  • 服务器端到客户端的通讯
  1. 当客户端与服务器端建立连接后;
  2. 服务器通过套节字对象调用write()函数发送上传内容;客户端会触发readyread信号
  3. 客户端在connect中处理readyread信号

客户端到服务器端实现代码:

//服务器端
 connect(server, QTcpServer::newConnection,
            [=]()
    {
       QTcpSocket socket = server->nextPendingConnection();
        connect(socket, &QTcpSocket::readyRead, [=]()
        {
            tp = socket->readAll();
            ui->textrc->append(tp);
        });
    }
    );
//客户端
void socket::on_buttonsend_clicked()
{
    QString temp = ui->textrc->toPlainText();
    if(!temp.isEmpty())sock->write(temp.toUtf8());

}

服务器端客户端实现代码:

//服务器端
void Widget::on_buttonsend_clicked()
{
    socket->write(ui->textEdit->toPlainText().toUtf8());
}
//客户端
    connect(sock, &QTcpSocket::readyRead,
            [=]()
    {
       ui->textdis->append(sock->readAll());
    });

完整代码:

服务器ui设计:

服务器端头文件widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_buttonsend_clicked();

private:
    Ui::Widget *ui;

    QTcpServer *server; //建立服务器对象
    QTcpSocket *socket; //套节字对象
    QByteArray tp;   //
};

#endif // WIDGET_H

服务器端cpp文件 widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("服务器");
    tp = nullptr;

    server = new QTcpServer(this);
    server->listen(QHostAddress::Any, 8000);
    connect(server, QTcpServer::newConnection,
            [=]()
    {
        socket = server->nextPendingConnection();
        connect(socket, &QTcpSocket::readyRead, [=]()
        {
            tp = socket->readAll();
            ui->testdis->append(tp);
        });
    }
    );

}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_buttonsend_clicked()
{
    socket->write(ui->textEdit->toPlainText().toUtf8());
}

客户端ui:

客户端头文件socket.h:

#ifndef SOCKET_H
#define SOCKET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>

namespace Ui {
class socket;
}

class socket : public QWidget
{
    Q_OBJECT

public:
    explicit socket(QWidget *parent = 0);
    ~socket();

private slots:

    void on_buttonLink_clicked();

    void on_buttonsend_clicked();

    void on_serverclose_clicked();

private:
    Ui::socket *ui;

    QTcpSocket *sock;
    QHostAddress adrs;
    quint16 port;
};

#endif // SOCKET_H

客户端cpp文件socket.cpp

#include "socket.h"
#include "ui_socket.h"

socket::socket(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::socket)
{
    ui->setupUi(this);
    sock = new QTcpSocket(this);
    setWindowTitle("张三");
    connect(sock, &QTcpSocket::readyRead,
            [=]()
    {
       ui->textdis->append(sock->readAll());
    });
}

socket::~socket()
{
    delete ui;
}

void socket::on_buttonLink_clicked()
{
    QString ip = ui->serverIP->text();
    QString p = ui->serverPort->text();
    sock->connectToHost(ip, p.toUShort());
}

void socket::on_buttonsend_clicked()
{
    QString temp = ui->textEdit->toPlainText();
    if(!temp.isEmpty())sock->write(temp.toUtf8());
}

void socket::on_serverclose_clicked()
{
    sock->close();
}

main.cpp文件

#include "widget.h"
#include <QApplication>
#include "socket.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    socket w1;
    w1.show();

    return a.exec();
}

最终运行效果:

当然在具体的实现过程中还有很多很多的细节需要优化;

QT5对tcp协议基本的通讯总结:

  • QTcpServer *p = new QTcpServer(this);//建立服务器对象               QTcpSocket *q = new QTcpSocket(this); //客户机建立套节字对象
  • p.listen(监听的客户ip , 监听端口port);//监听客户机           q.conncetToHost(要连接的服务器ip, 要连接的服务器端口);
  • connect(p, &QTcpServer::newConnection, )连接成功触发信号   q.write();//发送数剧 到服务器
  • QTcpSocket skt = p.nextPendingConnection();//获取客户机套节字     connect(q, &QTcpSocket::readyRead, )//服务端发送数据客户端触发信号
  • connect(skt, &QTcpSocket::readyRead, )//客户发送数据触发信号    q.readall();//读取客户端发送的数据;  
  • skt.readall();//读取客户端发送的数据;                                                       客户端处理数据
  • 服务器端处理数据 

QT5 UDP网络通讯 

UDP没有服务器与客户端之分;单纯通过writeDatagram发( 参数1, 参数2,参数3)送指定的内容(参数1)到指定的ip(参数2),端口(参数3)上;

当收取到网络中的数据发送,就会触发自己的readyRead信号;readDatagram(参数1, 参数2,参数3),保存读取的内容(参数1);保存对方ip(参数2);保存对方端口(参数3)

具体实现过程:

  • 建立QUdpSocket套节字                                                                                   QUdpSocket* p = new QUdpSocket(this);
  • 绑定本程序端口号 bind()                                                                                    p.bind(8000);
  • 通过writeDatagram()发送数据到指定目标                                                      p.writeDatagram();
  • 当有readyRead信号发生通过readDatagram()函数读取保存数据        p.readDatagram();

实现代码:

    QUdpSocket *udp = new QUdpSocket(this);
    udp->bind(8000);
    connect(udp, &QUdpSocket::readyRead, [=]()
    {

       char temp[1024] = {0};
       QHostAddress q;
       quint16 p;
       udp->readDatagram(temp, sizeof(temp), &q, &p);
       ui->textdis->append(temp);
    });

/......./

//按键确定发送
void Widget::on_buttonlink_clicked()
{
    udp->writeDatagram(ui->textsend->toPlainText().toUtf8(), QHostAddress(ui->ip->text()), ui->port->text().toUShort());
}

整体代码:

ui设计:

widget.h头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_buttonlink_clicked();

private:
    Ui::Widget *ui;
    QUdpSocket *udp;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>
#include <QDialog>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("8000");
    udp = new QUdpSocket(this);
    udp->bind(8000);
    udp->joinMulticastGroup(QHostAddress(""));
    connect(udp, &QUdpSocket::readyRead, [=]()
    {

       char temp[1024] = {0};
       QHostAddress q;
       quint16 p;
       udp->readDatagram(temp, sizeof(temp), &q, &p);
       ui->textdis->append(temp);
    });
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_buttonlink_clicked()
{
    udp->writeDatagram(ui->textsend->toPlainText().toUtf8(), QHostAddress(ui->ip->text()), ui->port->text().toUShort());
}

main.cpp文件

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

以便测试:我们先编译生成一份客户端;再在源文件中改变bind端口号为8888再生成一份客户端;最终就会有两份客户端以便相互通信测试

运行测试结果:

由于UDP不需要服务器,所以,UDP发送的数据,只要能接收到你的ip及端口的客户端就殾能收到信息;所以在局域网内,ip地址栏可输入

255.255.255.255 即整个局域网内的客户端都能收到信息;

UDP通讯组包

为了满足,发送的信息指定ip段内的客户收到信息可以用函数JoinMulticastGroup(IPAddress)加入到组;根据msdn记载,没错是同样的功能;

目前个人理解也不深;详细数据可查msdn;可用leaveMulticastGroup()函数离开组翻;

Tcp 与 Udp的比较:

Udp不需要服务器,只管发送数据,不对数据进行检查,也不对接收者检测;速度快,易丢包,做即时数据传送比较好;

 Tcp方式总结:

服务器端:QTcpServer

1】基本用法:

创建一个QTcpServer,然后调用listen函数监听相应的地址和端口。当有客户端链接到服务器时,会有信号newConnection()产生。

调用nextPendingConnection()接受一个挂起的TcpSocket连接,该函数返回一个指向QTcpSocket的指针,同时进入到QAbstractSocket::ConnectedState状态。这样就可以和客户端进行通信了。如果错误发生,可以用函数serverError()返回错误类型,用errorString()返回错误提示字符串。

调用close使得QTcpServer停止监听连接请求。尽管QTcpServer使用了事件循环,但是可以不这么使用。利用waitForNewConnection(),该函数阻塞直到有连接可用或者时间超时。

2】重要函数:

void incomingConnection (int socketDescriptor);

当一个连接可以用时,QTcpServer调用该函数。其基本过程是现创建一个QTcpSocket,设置描述符和保存到列表,最后发送newConnection() 事件消息。

QTcpSocket* QTcpServer::nextPendingConnection();

返回下一个将要连接的QTcpSocket对象,该返回对象是QTcpServer的子对象,意味着如果删除了QTcpSServer,则删除了该对象。也可以在你不需要该对象时,将他删除掉,以免占用内存。

客户端:QTcpSocket,QAbstractSocket

1】基本用法:

在客户端创建一个QTcpSocket,然后用connectToHost函数向对应的主机和端口建立连接。

任何时候,可以用state()查询状态,初始为UnconnectedState,然后调用连接函数之后,HostLookupState,如果连接成功进入ConnectedState,并且发送hostFound()信号。

当连接建立,发送connected(),在任何状态下如果在错误发生error()信号发送。状态改变发送stateChanged()信号。如果QTcpSocket准备好可读可写,则isValid() 函数范围为真。

用read()和write()来读写,或者使用readLine()和readAll.当有数据到来的时候,系统会发送readyRead()信号。

bytesAvailable()返回包的字节数,如果你不是一次性读完数据,新的数据包到来的时候将会附加到内部读缓存后面。setReadBufferSize()可以设置读缓存的大小。

用disconnectFromHost()关闭连接,进入ClosingState。当所有数据写入到socket,QAbstractSocket会关闭该台socket,同时发送disconnected()消息。

如果想立即终止一个连接,放弃数据发送,调用abort().

如果远程主机关闭连接,QAbstractSocket发送QAbstractSocket::RemoteHostClosedError错误,但是状态还停留在ConnectedState,然后发送disconnected()信号。

QAbstractSocket提供几个函数用来挂起调用线程,知道一定的信号发送,这些函数可以用来阻塞socket:

waitForConnected() 阻塞知道一个连接建立。

waitForReadyRead() 阻塞知道有新的数据可以读取。

waitForBytesWritten() 阻塞直到发送数据写道socket中。

waitForDisconnected() 阻塞知道链接关闭。

QT5 TCP网络通讯之文件传送

原文地址:https://www.cnblogs.com/flowingwind/p/8348519.html

时间: 2024-11-09 02:04:41

QT5 网络通讯的相关文章

Android网络通讯简介

网络通信应该包含三部分的内容:发送方.接收方.协议栈.发送方和接收方是参与通信的主体,协议栈是发送方和接收方进行通信的契约.按照服务类型,网络通信可分为面向连接和无连接的方式.面向连接是在通信前建立通信链路,而通信结束后释放该链路.无连接的方式则不需要在通信前建立通信连接,这种方式不保证传输的质量. Android提供了多种网络通信的方式,如Java中提供的网络编程,在Android中都提供了支持.Android中常用的网络编程方式如下: 针对TCP/IP协议的Socket和ServerSock

[转] C#.Net Socket网络通讯编程总结

1.理解socket1).Socket接口是TCP/IP网络的应用程序接口(API).Socket接口定义了许多函数和例程,程序员可以用它们来开发TCP/IP网络应用程序.Socket可以看成是网络通信上的一个端点,也就是说,网络通信包括两台主机或两个进程,通过网络传递它们之间的数据.为了进行网络通信,程序在网络对话的每一端都需要一个Socket. 2).TCP/IP传输层使用协议端口将数据传送给一台主机的特定应用程序,从网络的观点看,协议端口是一个应用程序的进程地址.当传输层模块的网络软件模块

《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT

感谢唯笑志在分享 原博主原地址:http://www.cnblogs.com/lsjwq/ 注:ServerSuperIO有可能被移植到Windows 10 IOT上,那么将来有可能开发一套设备驱动,可以支行在服务端.嵌入式设备中,将形成完整的解决方案.       现在已经调试通过部分代码,还得需要一段时间,一般都是晚上干,时间也有限.如下图: 目       录 4.如开发一套设备驱动,同时支持串口和网络通讯... 2 4.1           概述... 2 4.2          

网络--三种网络通讯方式及Android的网络通讯机制

Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口).Org.apache接口和Android.net.*(Android网络接口).下面分别介绍这些接口的功能和作用. 1.标准Java接口 java.net.*提供与联网有关的类,包括流.数据包套接字(socket).Internet协议.常见Http处理等.比如:创建URL,以及URLConnection/HttpURLConnection对象.设置链接参数.链接到服务器.向服务器写数据.从服务器读取

个人第一个开源分布式项目distributeTemplate的实现三 网络通讯netty传输大文件

今天 我将讲讲网络通讯,这里我初始版本 由于采用的事Netty框架  所以 这里讲网络Netty在我们这里是怎么使用的,下周开始添加rpc lucene内容了 实现之后的0.2 0.3版本,后面将会去掉netty依赖 采用原生的NIO2 (aio) 异步非阻塞方式 实现自己网络通讯,也就是说 这部分可能会实现一个简单的但是比netty精简高效的网络框架,后期做出来 可能会单独开一个分支开源出来,netty说白了 就是 事件驱动 以及 NIO 加一些协议 以及 异常 处理,废话不多说了. 我最近

C#.NET通过Socket实现平行主机之间网络通讯(含图片传输的Demo演示)

在程序设计中,涉及数据存储和数据交换的时候,不管是B/S还是C/S模式,都有这样一个概念:数据库服务器.这要求一台性能和配置都比较好的主机作为服务器,以满足数目众多的客户端进行频繁访问.但是对于一些数据交换的要求不主同,而且涉及到的通讯个体数目不多,如果还采用“一主机多客户机”的模式,便要求一台硬件配置良好而且软件上安装了相关数据服务软件,这样会造成硬件和软件上的很多不必要的成本,这时Socket在点对点的平行对象之间的网络通讯的优势就就发挥出来了. 其实对于Socket通讯来说,服务器和客户端

网络通讯之套接字编程

#include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> static char out_ip[15] = "52.0.10.188"; static int out_port = 8888; int main() { char sSendBuf[2049], sRecvBuf[2049]; int connfd = 0, iRet = 0, iSendLen = 0; struc

Qt的Model/View Framework解析(数据是从真正的“肉(raw)”里取得,Model提供肉,所以读写文件、操作数据库、网络通讯等一系列与数据打交道的工作就在model中做了)

最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章.E文的除了Qt的官方介绍,其它文章也很少.看到一个老外在blog中写道Model/View是他认为Qt中最不好的一部分了.真的是这样吗?为了回馈开源社区,我写了这篇blog,写的是我认为比较有价值的东东.题目起得是解析,但也没有特别细节的介绍,点到为止,有兴趣的Tx可以继续讨论.我所看的资料有<C++ GUI Programming with Qt 4, Second Edition

网络通讯框架MINA和XSCOCKET的简单比较

http://www.blogjava.net/ghostdog/archive/2008/06/10/MinaVsXsocket.html实在无聊,考虑把当前应用的通讯模式由http移植为socket, 服务器这块因为对NIO并不熟悉,所以考虑使用现成的网络通讯框架进行移植,花了点时间测试比较流行的mina和xsocket.== 相同点 ==  1. 都对nio进行了有效屏蔽, 可以简化开发过程, 对于文本流模式的应用,两者都非常简单,实现一个基本的handle就可以  2. 提供了一些常见的